Shadow of the Beast (port)

A place where you can keep others updated about your NES-related projects through screenshots, videos or information in general.

Moderator: Moderators

User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Shadow of the Beast (port)

Post by dougeff »

It seems the neslib based source code on my webpage omits this bit

lda #$40
sta $4017

from crt0.s

I believe I borrowed this crt0 from the Alter Ego source code.

$4017 is the APU frame counter. Writing #$40 here disables frame count IRQs. Please add this somewhere near the top of crt0.s. Sorry for the inconvenience.
(I quoted myself because this is the first comment on a new page of comments, and I want to keep the context of the conversation in place).

Once I edited that line in...it works in most emulators. It doesn't work in Nintendulator.

I think the reason is because you put the reset code at $8458 in the swappable bank. reset code should be at $e000-ffff in the fixed bank. And your reset code should explicitly put the correct banks in place before you use them.

I think, if you did those 2 fixes, it would would in nearly all emulators.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Shadow of the Beast (port)

Post by Diskover »

Thanks dougeff

It seems that the problem was solved adding those two lines after start: in crt0.s

Here you have the new rom arranged: Shadow of the Beast (alpha 0.2) [HB].nes

However, I do not understand that of the bank $8458 ¿?¿?¿?

I have not touched anything there :(
Sour
Posts: 890
Joined: Sun Feb 07, 2016 6:16 pm

Re: Shadow of the Beast (port)

Post by Sour »

On MMC3, only the last bank is guaranteed to be mapped to a specific part of PRG ROM at power on.
So if your reset vector is not within the $E000-$FFFF range, there's no guarantee it will work properly on a real cart.

If I turn on the "Randomize mapper state at power on" option in Mesen, the game mostly crashes/freezes instead of booting (because the part of PRG ROM that is mapped to $8000-$9FFF is random, instead of always being bank 0)
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Shadow of the Beast (port)

Post by rainwarrior »

Ahh, good to see it working. Yes, my PowerPak test was NTSC, did not realize it was to be PAL until you said so.

BTW you can get some emulators to automatically select PAL with "(E)" in the filename. I think you could also use an iNES 2 header to specify PAL, but only some newer emulators will use this.
Diskover wrote:However, I do not understand that of the bank $8458 ¿?¿?¿?

I have not touched anything there :(
MMC3 powers on with a "random" bank at that address. Only $E000-$FFFF is fixed, so your RESET vector should point there for it to reliably boot on a real cart. (Everdrive and PowerPak do not simulate this, they don't boot a ROM from power-on, so some banks are already set up.)

To do this, you could add a segment to your config file in the last bank with e.g. start=$FF00 and stick a reset stub in that segment. (Whatever you're doing for the vectors segment already, you can do similarly.)
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Shadow of the Beast (port)

Post by Diskover »

rainwarrior wrote:Ahh, good to see it working. Yes, my PowerPak test was NTSC, did not realize it was to be PAL until you said so.

BTW you can get some emulators to automatically select PAL with "(E)" in the filename. I think you could also use an iNES 2 header to specify PAL, but only some newer emulators will use this.

MMC3 powers on with a "random" bank at that address. Only $E000-$FFFF is fixed, so your RESET vector should point there for it to reliably boot on a real cart. (Everdrive and PowerPak do not simulate this, they don't boot a ROM from power-on, so some banks are already set up.)

To do this, you could add a segment to your config file in the last bank with e.g. start=$FF00 and stick a reset stub in that segment. (Whatever you're doing for the vectors segment already, you can do similarly.)
I have not intended it to be PAL. It should work in NTSC and PAL, or at least that's what I want.

When I get home (right now I'm at work) I look at these vectors, but I insist that I have not touched anything that makes them change to something "random". The truth is that I am confused about this. But I will review it.
User avatar
Sumez
Posts: 919
Joined: Thu Sep 15, 2016 6:29 am
Location: Denmark (PAL)

Re: Shadow of the Beast (port)

Post by Sumez »

Random is exactly what happens when you don't touch anything.

It's my experience that almost all issues with certain emulators or real hardware come from failing to initialize everything you need. This includes both clearing RAM, setting hardware states (such as enabling IRQ), and configuring your mapper chip. You have to rely on a static bank with your reset vector in it, and within this bank you add your initialization code to make sure the remaining banks are mapped correctly.

The last similar issue I ran into was a feature I had completely forgotten in the MMC3 - writing to the cartridge RAM is impossible if the write lock is set, and just like everything else, it might "randomly" be so on hardware or certain emulators.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: Shadow of the Beast (port)

Post by Banshaku »

MMC3 banks are not set by default on hardware. I had that issues when I did my first tests 8 years ago on my dev cartridge and all my chr banks where scrambled. The emulators were setting them to a predefined default when it was not the case on the real thing. Once I found that then my code was working fine.
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Shadow of the Beast (port)

Post by Diskover »

The same is that I explain myself wrongly.

The whole basis with which I made the MMC3 part of this dougeff guide: https://nesdoug.com/2016/01/15/24-mmc3- ... hing-irqs/

The configuration of the CFG is as follows:

Code: Select all

#ROM Addresses:
 #they are all at $8000, because I will be swapping them into that bank
 PRG0: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG1: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG2: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG3: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG4: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG5: start = $a000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG6: start = $c000, size = $2000, file = %O ,fill = yes, define = yes;
 PRG7: start = $e000, size = $1ffa, file = %O ,fill = yes, define = yes;

# Hardware Vectors at end of the ROM
 VECTORS: start = $fffa, size = $6, file = %O, fill = yes;

User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Shadow of the Beast (port)

Post by dougeff »

Yes, but look down in "segments" in nes.cfg.

Is "startup" mapped to PRG7? It is for the example code. and when I run mine, and pause execution, and hit reset, I see in the debugger that it jumps to $e005.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Shadow of the Beast (port)

Post by Diskover »

Let's see.

The rest of the instructions I have them put like this:

Code: Select all

#1 Bank of 8K CHR ROM
    CHR: start = $0000, size = $10000, file = %O, fill = yes;
}

SEGMENTS {
    HEADER:   load = HEADER,         type = ro;
    CODE0:    load = PRG0,           type = ro,  define = yes;
    CODE1:    load = PRG1,           type = ro,  define = yes;
    CODE2:    load = PRG2,           type = ro,  define = yes;
    CODE3:    load = PRG3,           type = ro,  define = yes;
    CODE4:    load = PRG4,           type = ro,  define = yes;
    CODE5:    load = PRG5,           type = ro,  define = yes;
    CODE6:    load = PRG6,           type = ro,  define = yes;
    STARTUP:  load = PRG0,           type = ro,  define = yes;
	
    CODE:     load = PRG7,           type = ro,  define = yes;
    VECTORS:  load = VECTORS,        type = ro;
    CHARS:    load = CHR,            type = rw;
	
    LOWCODE:  load = PRG7,            type = ro,                optional = yes;
    
    INIT:     load = PRG7,            type = ro,  define = yes, optional = yes;
    RODATA:   load = PRG7,            type = ro,  define = yes;
    DATA:     load = PRG1, run = RAM, type = rw,  define = yes;
    MAP:	  load = MAP1,			 type = bss, define = yes;
    BSS:      load = RAM,            type = bss, define = yes;
    HEAP:     load = RAM,            type = bss, optional = yes;
    ZEROPAGE: load = ZP,             type = zp;
    #ONCE:     load = PRG,            type = ro,  define = yes;
}
Now I remember that STARTUP I put in PRG0 because in PRG7 I did not enter anymore. As I saw that it worked, I did not give importance to it.
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Shadow of the Beast (port)

Post by dougeff »

It's important. So let's try to resolve.

"CODE" is where cc65 puts the C library. That's probably filling up PRG7, and why you can't put more there. Or perhaps you put the music in "CODE" or "STARTUP", filling it.

Try putting "CODE" in PRG6, and "STARTUP" in PRG7.

If that doesn't work, try putting the music in another segment.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Shadow of the Beast (port)

Post by Diskover »

Is this correct?

Code: Select all

     CODE:     load = PRG0,           type = ro,  define = yes;
     STARTUP:  load = PRG7,           type = ro,  define = yes;
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Shadow of the Beast (port)

Post by dougeff »

Well, I suggested CODE in PRG6.

That would put it in PRG0.

Give it a try, either way. See if it compiles.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Shadow of the Beast (port)

Post by Diskover »

Ok, done, but I do not know what I've played now that when I turn on the music, the game does not work correctly: cry:
Attachments
Shadow of the Beast (alpha 0.3) [HB].nes
(128.02 KiB) Downloaded 344 times
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Shadow of the Beast (port)

Post by rainwarrior »

My assumption is that you're running your music within the NMI.

The reason this is a problem is that NMI implicitly does a SEI (cleared by the RTI popping the processor flags). So if your music update happens in your NMI routine, it will overlap and block your interrupts if it takes too long, which it does on NTSC.

Easy fix: just put a CLI in the NMI routine just before it calls the music playback (assuming it is the last thing that happens in your NMI handler). Otherwise if that's not feasible, you can just move the music playback outside of the NMI. It doesn't really matter too much where it gets called as long as it's once per frame, preferably at a consistent time (which is why NMI is usually convenient).


Edit: Actually, peeking at it in a debugger, it looks like your NMI is missing an RTI at the end? It seems to roll right into the IRQ handler after finishing. So in this case, I'd recommend putting a CLI before the music playback there, and also an RTI before the IRQ handler begins.

Code: Select all

 03:E224: A9 00     LDA #$00
 03:E226: 85 02     STA $02 = #$03
 03:E228: 20 4C E8  JSR $E84C ; music playback? place a CLI right before this line
 03:E22B: 68        PLA
 03:E22C: A8        TAY
 03:E22D: 68        PLA
 03:E22E: AA        TAX
 03:E22F: 68        PLA ; shouldn't an RTI follow this line?
>03:E230: 48        PHA ; IRQ handler starts here
 03:E231: 8A        TXA
 03:E232: 48        PHA
 03:E233: 98        TYA
 03:E234: 48        PHA
...
 03:E260: 40        RTI
Post Reply