Shadow of the Beast (port)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Shadow of the Beast (port)
by on (#217406)
Image


Title: Shadow of the Beast
Original company: Psygnosis
Port: RetroNES Software
Console: NES (8 bits)
Mapper: MMC3
Librery: NESlib (Shiru)
Multiscroll engine: Doug Fraker
Music: MovieMovies1, arreglada para que funcione en MMC3
ROM: Shadow of the Beast (alpha 0.34) [HB].nes


Youtube: https://www.youtube.com/watch?v=PthPqjZslEA

https://twitter.com/RetroNES_Soft/statu ... 1169505281

Many of you have already seen it on my Twitter account, but there it goes:

Shadow of the Beast is a videogame developed by Psygnosis in 1989 for the Amiga computer, and later programmed in many other platforms of 8 and 16 bits ... except NES.

This video game, although it is not remarkable when playing, was very famous at that time due to its artistic and musical section.

Several users of the EOL forum, after discussing 8-bit and 16-bit video games that attracted attention in the 80s and 90s, talked about this videogame and how rare it was that it did not appear on NES when on most other platforms there was a version, even in Sega Master System.

Many possibilities were considered regarding its possible technical realization in NES and I proposed a demonstration about its viability.

The result is as follows.

NROM
Image


Then I proposed to make a demonstration using the MMC3 for the IRQ interrupts and to be able to make the effect of the clouds.
MMC3
Image

You can still improve, add more animations, etc ... For its realization, as always, I used the CC65 compiler and the NESlib library of Shiru. To make the MMC3 work, I've helped with the @dougeff tutorial

I do not intend to make the whole game, but simply show what NES could be capable of with this videogame.

Until I have a decent ROM I will not share anything

More info: https://www.elotrolado.net/hilo_homebre ... ca_2282337
Re: Shadow of the Beast (port)
by on (#217408)
I've always had a fond admiration for that game. Best of luck!
Re: Shadow of the Beast (port)
by on (#217410)
Sounds like a great project. Good luck! :)
Re: Shadow of the Beast (port)
by on (#217703)
- April 28, 2018: we add the fence silhouetted, below.
Image
Re: Shadow of the Beast (port)
by on (#217729)
Do you have any NTSC filtered screenshots? In the pictures, the sky colors are just too far apart to use dithering to make a convincing gradient, imo, so I was wondering if it would look any better with an NTSC filter.
Re: Shadow of the Beast (port)
by on (#217746)
Espozo wrote:
Do you have any NTSC filtered screenshots? In the pictures, the sky colors are just too far apart to use dithering to make a convincing gradient, imo, so I was wondering if it would look any better with an NTSC filter.


I do not have NTSC TV, I'm from Spain and here everything works in PAL.

I have two videos from an LED screen, and soon I will upload one from CRT to see if there is much difference and the color gradient works.

https://www.youtube.com/watch?v=W_TrfDLk6S0
Re: Shadow of the Beast (port)
by on (#217755)
This is a question I've always had: is it just harder to code that many splits in the scrolling or does it have a high cpu cycle cost? What is the most that has ever been done in a gameplay section of a game?

Anyway, I never understood the appeal to this game, but I didn't get to know it until the 16-bit era of consoles. This looks very nice!
Re: Shadow of the Beast (port)
by on (#217756)
nesrocks wrote:
This is a question I've always had: is it just harder to code that many splits in the scrolling or does it have a high cpu cycle cost? What is the most that has ever been done in a gameplay section of a game?

It's say Recca took it as far as it ever went on NES:
https://youtu.be/EE5URFvZfHo?t=5m25s

There are a bunch of others that have a high number of splits. Rad Racer, Tetrastar, etc.

With an IRQ they take up a much smaller cycle cost than without one, 'cause you can keep executing code between the splits. Without the IRQ you have to dedicate the whole CPU to splits until you're done splitting (e.g. this is why half the screen is sky in Rad Racer, time to get the other work done).
Re: Shadow of the Beast (port)
by on (#217768)
And now to work in the forest

Image
Re: Shadow of the Beast (port)
by on (#217776)
Definitely looks better now that the colors are closer together.

Have you ever considered doing something like this to also make the transformation smoother? I didn't bother trying to put it "behind" the trees, even though you'd obviously want to do that.
Re: Shadow of the Beast (port)
by on (#217777)
Image

Ok, @Espozo I'll keep it in mind next time.
Re: Shadow of the Beast (port)
by on (#217778)
@espozo: Actually curved gradients like that can help a lot with making something look more alive and less a pattern... even if you did it to avoid the work around the trees. 8-) Tough to pull off with scrolling though as you don't want that to scroll at all.
Re: Shadow of the Beast (port)
by on (#217787)
Ok?

Image
Re: Shadow of the Beast (port)
by on (#217788)
Home. <3
Re: Shadow of the Beast (port)
by on (#217970)
Diskover wrote:
Several users of the EOL forum, after discussing 8-bit and 16-bit video games that attracted attention in the 80s and 90s, talked about this videogame and how rare it was that it did not appear on NES when on most other platforms there was a version, even in Sega Master System.

I was about to point out that it's very common that an inherent Amiga game doesn't get an NES port, but looking it up, I'm absolutely baffled how many ports this game actually did get!
I've always seen the game as primarily an Amiga title, and basically a tour de force of showing off what the system can do, with very little care taken into how it actually played.

Your videos are really amazing looking, and I'm very interested in seeing how the demo ends out on the NES, backed by your expertise. Would it be too much to also wish for an attempt at fixing the terrible gameplay, and make it into a fun game to play as well? :D Or are you only focusing on recreating the graphical experience?
Re: Shadow of the Beast (port)
by on (#218032)
Sumez wrote:
I was about to point out that it's very common that an inherent Amiga game doesn't get an NES port, but looking it up, I'm absolutely baffled how many ports this game actually did get!
I've always seen the game as primarily an Amiga title, and basically a tour de force of showing off what the system can do, with very little care taken into how it actually played.

Your videos are really amazing looking, and I'm very interested in seeing how the demo ends out on the NES, backed by your expertise. Would it be too much to also wish for an attempt at fixing the terrible gameplay, and make it into a fun game to play as well? :D Or are you only focusing on recreating the graphical experience?


This is just a technical / graphic demonstration.

I do not have enough capacity or knowledge to make the whole game.

Having an engine that makes me scroll simply is almost impossible for me. Imagine making an engine that contemplates multi-directional scroll.

I have been playing with the MMC3. I can split the screen into pieces to simulate parallax, I can even play to change CHR banks partially, and little else.
Re: Shadow of the Beast (port)
by on (#218033)
I've been in the scene for years, and I've made an engine capable of 8-directional scrolling. (I cannot give a release date because it is for a client.) But even I shudder at the thought of making an engine that updates the tilemap for different layers at different speeds, as would be required for having one of the layers be more than 512 pixels in width, and combining that feature with 8-directional scrolling.
Re: Shadow of the Beast (port)
by on (#218204)
For me the hardest part would be getting the large enemies on screen without it being a flicker fest, the game likes everything big.
Re: Shadow of the Beast (port)
by on (#218206)
AVS and NT mini would handle it better of course, even if most'd play it on the NES or on a NES emulator.
Re: Shadow of the Beast (port)
by on (#218247)
Oziphantom wrote:
For me the hardest part would be getting the large enemies on screen without it being a flicker fest, the game likes everything big.


In the Sega Master System version, what they do when they arrive at these meetings is to move to a screen where the background is the boss.

https://youtu.be/BnwOih21rbE?t=8m3s


FrankenGraphics wrote:
AVS and NT mini would handle it better of course, even if most'd play it on the NES or on a NES emulator.


What is AVS and NT mini?
Re: Shadow of the Beast (port)
by on (#218249)
Diskover wrote:
What is AVS and NT mini?

Recent clone systems that both (?) have an option to double the sprite limit to 16 instead of 8, if I recall. (Not sure about the NT, but I'll assume yes based on that comment.)

AVS: http://www.retrousb.com/product_info.php?products_id=78

The NT is perpetually unavailable, but there are at least a few out there in the world: https://www.analogue.co/pages/nt-mini/
Re: Shadow of the Beast (port)
by on (#218250)
rainwarrior wrote:
Diskover wrote:
What is AVS and NT mini?

Recent clone systems that both (?) have an option to double the sprite limit to 16 instead of 8, if I recall. (Not sure about the NT, but I'll assume yes based on that comment.


Overcoming that limit is very interesting, but ... I would like to stick to the real limitations of the NES.

As before, there are solutions, and in Sega Master System became the bosses in part of the background, as happened in many NES games as well.
Re: Shadow of the Beast (port)
by on (#218252)
rainwarrior wrote:
that both (?) have an option to double the sprite limit


Yeah, both have a 16 sprites per scanline mode.

NT mini will likely be unavailable for quite some time due to the unexpected demand of their super famicom clone. Preorders of the second batch of those are estimated to ship this autumn and it seems it's all hands on deck to get those out first before resuming production of the nt mini:

https://support.analogue.co/hc/en-us/ar ... ailability

the Super NT is priced to sell, unlike NT/NT mini which are de luxe. I predict they'll come up with a new, cheaper case option for the NT mini following the success of the Super NT eventually.

diskover wrote:
I would like to stick to the real limitations of the NES.

And it's very reasonable to do so. Still, these fpga clones will yield a smoother experience of let's say bubble bobble or castlevania even though these games weren't designed around a higher sprites per scanline tolerance.
Re: Shadow of the Beast (port)
by on (#218308)
First scroll tests.
The engine used for this scroll is the All-direction scrolling (with small modifications), by Doug Fraker.
Its peculiarity lies in that it works under the NES 4-screen format.
I have to solve errors.

https://www.youtube.com/watch?v=FFKp4oZ21F8
Re: Shadow of the Beast (port)
by on (#218309)
I don't know if this is a property of the original game or not, but however dynamic and impressive looking all the parallax is, i think the clouds come off as unnatural when they scroll that fast. They're probably the most distanced objects depicted or at least on an approximate depth level with the mountains, yet they react to camera position like they were hanging in front of everything, which would probably work great for a mist or the like. I'd probably leave clouds scrolling on speed with or slower than the mountains when it's contingent on camera/player movement, but ever so slowly auto-scrolling to indicate movement, wind and depth.
Re: Shadow of the Beast (port)
by on (#218339)
That's what the original game is like. Or well, almost. They are really "low hanging" clouds.

Honestly, I think it's an artistic freedom games should be able to take. I love scrolling clouds like that. Nothing to build a creepy atmosphere like SOTN-style fast clouds, too.
Re: Shadow of the Beast (port)
by on (#218356)
They don't really scroll that fast in the original:
https://www.youtube.com/watch?v=73JBaFkNZaE&t=12m26s

...but I mean, Diskover is just getting the scrolling working at this point. Tweaking the speed is a trivial adjustment.

Myself I'm hoping there's a few sprites left on the scanline for a blimp. ;)

There's a nice facsimile here, though missing the blimp:
http://www.int33h.com/test/shadow/
Re: Shadow of the Beast (port)
by on (#218477)
Put a forest in your life.
Image
Re: Shadow of the Beast (port)
by on (#218723)
inside the tree
Image
Re: Shadow of the Beast (port)
by on (#219577)
Very nice
Re: Shadow of the Beast (port)
by on (#219940)
In the next few days I will release the rom demo of Shadow of the Beast for NES.

The truth is that it has taken a lot of time away from other projects because I got hooked on making it work despite my limitations and the limitations of the machine. A team of professionals would have polished it without much trouble.

In fact, the rom contains some flaw, much more visible in emulator, but functional in a real NES console through everflash, etc ...

I'm very excited about it, but I want to leave it here to continue with the remodeling of my most important project: The Banketh

Image
Re: Shadow of the Beast (port)
by on (#220953)
ROM: http://www.retrones.net/sites/default/f ... BHB%5D.nes

It has been developed with support from the NESlib library of Shiru. The multidirectional scroll is a modification of the original engine of Doug Fraker, which has also been adapted to work with the mapper MMC3 (to achieve plane effects). I found the music by chance in a forum dedicated to famitraker, and it was developed by MovieMovies1 for the mapper MMC5. Obviously, I have adapted it to work in the MMC3.

It works perfectly on a real NES using flashcard and other methods.

If you want to use it on PC or smartphone, the VirtuaNES emulator is recommended.
Re: Shadow of the Beast (port)
by on (#220958)
This ROM fails in 5 of the 6 emulators I tried. It worked in JNES 1.1, with a few errors.
Re: Shadow of the Beast (port)
by on (#220959)
It isn't quite working for me on my PowerPak either. Seems playable but some of the graphics are displaying the wrong tiles, and the scroll splits seem broken every second frame? (Seen as interlaced lines in the picture below.)

I dunno what your goals are, but it's probably worth trying to do this in a way that plays nice with most emulators? Unless you're specifically trying to exploit something technical that only the "real thing" can do, you're probably relying on some specific quirk of the implementation of MMC3 used by your flashcart which may or may not be present on an actual MMC3. (Clearly my PowerPak's simulation of an MMC3 differs from the one you used on your flashcart.) If you write code that is more within the boundaries of the well known parts of the MMC3 though, it should run on more emulators too.

Otherwise, I am excited to see this ready for public viewing. :)
Re: Shadow of the Beast (port)
by on (#220967)
Seems to work fine on my Everdrive. Did not work on FCEUX when I tried immediately after I downloaded.
Re: Shadow of the Beast (port)
by on (#220970)
I recommend using the VirtuaNES emulator or in a real NES using flashcard

http://virtuanes.s1.xrea.com/bin/virtuanes097e.zip

I spent a lot of time trying to solve the errors in the other emulators, but it has been impossible for me.

The problem is when I activate the instruction asm ('cli'); for the interruption of the MMC3 to work.

Guide me through the dougeff MMC3 tutorial https://nesdoug.com/2016/01/15/24-mmc3- ... hing-irqs/
Re: Shadow of the Beast (port)
by on (#220972)
Like rainwarrior said, unless you're intentionally exploiting hardware quirks that emulators are known to have problems with, it's a good idea to look into why it fails on so many setups. Even if it does work on real hardware (although it seems that different MMC3 implementations in flash carts are still disagreeing), and theoretically the original console has the final word, the fact that slight deviations from the real hardware are causing visible problems could mean your code is barely working, and under certain circumstances could still break.

A lot of these emulators are pretty accurate (unlike VirtuaNES, from what I could find online) and can handle all sorts of games just fine, so they should be able to handle your effects without problems too. I think the effort of making this game/demo work well across different emulators is worth it, as you'll end up with a more robust engine overall.
Re: Shadow of the Beast (port)
by on (#220974)
tokumaru wrote:
Like rainwarrior said, unless you're intentionally exploiting hardware quirks that emulators are known to have problems with, it's a good idea to look into why it fails on so many setups. Even if it does work on real hardware (although it seems that different MMC3 implementations in flash carts are still disagreeing), and theoretically the original console has the final word, the fact that slight deviations from the real hardware are causing visible problems could mean your code is barely working, and under certain circumstances could still break.

A lot of these emulators are pretty accurate (unlike VirtuaNES, from what I could find online) and can handle all sorts of games just fine, so they should be able to handle your effects without problems too. I think the effort of making this game/demo work well across different emulators is worth it, as you'll end up with a more robust engine overall.


I have not done anything particularly weird to make the game work. As I mention, when implementing the MMC3, at the moment I activate the instruction asm ('cli'); for interruptions per line to work, in most emulators it stops working. On the other hand, in VirtuaNES and in a real NES it works perfectly.

If I deactivate the instruction asm ('cli'); the game works on all
Re: Shadow of the Beast (port)
by on (#220975)
rainwarrior wrote:
It isn't quite working for me on my PowerPak either. Seems playable but some of the graphics are displaying the wrong tiles, and the scroll splits seem broken every second frame? (Seen as interlaced lines in the picture below.)

I dunno what your goals are, but it's probably worth trying to do this in a way that plays nice with most emulators? Unless you're specifically trying to exploit something technical that only the "real thing" can do, you're probably relying on some specific quirk of the implementation of MMC3 used by your flashcart which may or may not be present on an actual MMC3. (Clearly my PowerPak's simulation of an MMC3 differs from the one you used on your flashcart.) If you write code that is more within the boundaries of the well known parts of the MMC3 though, it should run on more emulators too.

Otherwise, I am excited to see this ready for public viewing. :)


The sprites work under the 8x16 configuration

From what I see, it seems that your PowerPak has not identified them that way and tries to show them as 8x8

I have an idea: this afternoon, when I leave work, I will put the game on an MMC3 board.

I think I remember that I have PRG and CHR stored in some box. I will flase, weld and try with the MMC3 of RetroStage.-
Re: Shadow of the Beast (port)
by on (#220984)
If you are setting and clearing interrupts 200+ times a frame, this may be the problem.

Other games don't do this, which is why no emulator author has bothered to get the accuracy perfect on such a thing.

MMC3 has a scanline counter system. I would use that. That just requires keeping interrupts ON the whole frame and just resetting a counter value several times a frame.


Also, are you using a PAL NES, diskover? That might be part of the issues that rainwarrior is having.

Quote:
I will put the game on an MMC3 board
You might have issues, if the board doesn't have 4 screen mirroring, like the ROM.
Re: Shadow of the Beast (port)
by on (#220986)
Yes, I am using a PAL NES

I configured this in this way to be able to do 15 screen divisions and in that way make parallax scroll effects.

Code:
irq:
   pha
   txa
   pha
   tya
   pha
   ldy #15            ;wait a little, loop 15 times
:   dey               ;2 cycles
   bne :-             ;3 cycles

   ldx _Scroll_Index    ;each time the irq fires, it fetches a different byte from and array
   lda _Scroll, x
   sta $2005         ;change the horizontal scroll
   lda _scrollY       ;#0 originalmente. Controlamos desplazamiento vertical de la pantalla
   sta $2005         ;vertical scroll = 0
   inc _Scroll_Index

   lda #1
   sta $e000          ; acknowledge the irq, turn off the counter
   lda #14            ; Alto en pixeles de cada linea IRQ. Tenemos 10 trozos a repartir. Hay que probar con 32
   sta $c000          ; set up the next irq, 20 scanlines   
   sta $c001
   lda #1
   sta $e001          ; turn on the scanline counter
   
   pla
   tay
   pla
   tax
   pla
   rti
Re: Shadow of the Beast (port)
by on (#221321)
The problem is that you did not disable APU Frame Counter IRQs at power on. These are enabled by default, at least on NTSC consoles (and likely most emulators): http://wiki.nesdev.com/w/index.php/CPU_power_up_state)

Changing Mesen's code to boot with APU IRQs disabled fixes (almost) everything:
Attachment:
shadow.png
shadow.png [ 25.98 KiB | Viewed 4183 times ]
I say almost because at some very specific character positions, the background (between the clouds & ground) flashes in or out of existence for a few pixels.

This issue reminds me of this problem bananmos had with a PAL rom: viewtopic.php?p=214822#p214822
It's possible that PAL NES might boot with the "disable IRQ" flag turned on for the frame counter, which would explain both issues. (I'm unsure if any of the PAL test roms check this particular behavior)
Re: Shadow of the Beast (port)
by on (#221378)
Sour wrote:
The problem is that you did not disable APU Frame Counter IRQs at power on. These are enabled by default, at least on NTSC consoles (and likely most emulators): http://wiki.nesdev.com/w/index.php/CPU_power_up_state)

Changing Mesen's code to boot with APU IRQs disabled fixes (almost) everything:
I say almost because at some very specific character positions, the background (between the clouds & ground) flashes in or out of existence for a few pixels.)


Yes, it is a problem that I have not been able to solve and that has to do with the camera that follows the player. For 4 pixels, it is positioned in the previous nametable. I tried many things, such as delaying a few pixels, but this generated other new problems, and I gave up. Also in PAL console this small defect occurs.

It only happens when we work with MMC3 and the IRQs are on. If I deactivate it, it does not happen.

Sour wrote:
This issue reminds me of this problem bananmos had with a PAL rom: viewtopic.php?p=214822#p214822
It's possible that PAL NES might boot with the "disable IRQ" flag turned on for the frame counter, which would explain both issues. (I'm unsure if any of the PAL test roms check this particular behavior)


And what is the solution if the IRQs should always be on to make the parallax scroll effect?
Re: Shadow of the Beast (port)
by on (#221387)
Manually turn it on? :)
Re: Shadow of the Beast (port)
by on (#221399)
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.
Re: Shadow of the Beast (port)
by on (#221400)
Quote:
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.
Re: Shadow of the Beast (port)
by on (#221438)
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 :(
Re: Shadow of the Beast (port)
by on (#221440)
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)
Re: Shadow of the Beast (port)
by on (#221441)
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.)
Re: Shadow of the Beast (port)
by on (#221480)
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.
Re: Shadow of the Beast (port)
by on (#221483)
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.
Re: Shadow of the Beast (port)
by on (#221486)
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.
Re: Shadow of the Beast (port)
by on (#221500)
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:
#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;

Re: Shadow of the Beast (port)
by on (#221508)
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.
Re: Shadow of the Beast (port)
by on (#221512)
Let's see.

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

Code:
#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.
Re: Shadow of the Beast (port)
by on (#221520)
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.
Re: Shadow of the Beast (port)
by on (#221528)
Is this correct?

Code:
     CODE:     load = PRG0,           type = ro,  define = yes;
     STARTUP:  load = PRG7,           type = ro,  define = yes;
Re: Shadow of the Beast (port)
by on (#221537)
Well, I suggested CODE in PRG6.

That would put it in PRG0.

Give it a try, either way. See if it compiles.
Re: Shadow of the Beast (port)
by on (#221538)
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:
Re: Shadow of the Beast (port)
by on (#221539)
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:
 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
Re: Shadow of the Beast (port)
by on (#221612)
Ah, I see the problem. Wasn't quite where I was suggesting, though related:

You set up your first IRQ here in your main thread code. This happens directly after the NMI returns:
Code:
 00:9BB8: 20 C0 E3  JSR $E3C0 ; wait for NMI
>00:9BBB: A9 01     LDA #$01 ; setup first interrupt
 00:9BBD: 8D 00 E0  STA $E000
 00:9BC0: 8D 00 C0  STA $C000
 00:9BC3: A9 00     LDA #$00
 00:9BC5: 8D 01 C0  STA $C001
 00:9BC8: A9 01     LDA #$01
 00:9BCA: 8D 01 E0  STA $E001
 00:9BCD: A9 00     LDA #$00
 00:9BCF: 85 74     STA $74


The problem is that the music routine delays when you will return from NMI. On PAL there is plenty of time for it to execute before rendering begins, but on NTSC it will overlap the beginning of the frame sometimes. If this first IRQ setup doesn't happen before scanline 0, the whole screen is thrown off. (Seems to be about 10-15 scanlines late on every other frame.)

The solution should be to put this inside your NMI handler. See my last suggestion from my previous post, you should still add that CLI and RTI, but right there above the suggested CLI do this first IRQ setup right there, when you know you're still in vblank (i.e. before scanline 0) and you haven't yet run the music routine. This will allow that first IRQ to fire on scanline 0 (which will sometimes be within the music routine, but it is perfectly okay to interrupt that).


Alternative option is to put the music playback call in your main thread just after that STA $74. This will get your NMI handler returning earlier again.

Ideally both of these things should be within the NMI, though. Having the IRQs set off by the NMI will prevent them from failling if your main thread ever runs too long (slowdown), and similar with music having it in the NMI makes it slowdown resitant. However, if you can guarantee the main thread will never run long it doesn't matter either way.
Re: Shadow of the Beast (port)
by on (#221714)
rainwarrior wrote:
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:
 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


rainwarrior wrote:
Ah, I see the problem. Wasn't quite where I was suggesting, though related:

You set up your first IRQ here in your main thread code. This happens directly after the NMI returns:
Code:
 00:9BB8: 20 C0 E3  JSR $E3C0 ; wait for NMI
>00:9BBB: A9 01     LDA #$01 ; setup first interrupt
 00:9BBD: 8D 00 E0  STA $E000
 00:9BC0: 8D 00 C0  STA $C000
 00:9BC3: A9 00     LDA #$00
 00:9BC5: 8D 01 C0  STA $C001
 00:9BC8: A9 01     LDA #$01
 00:9BCA: 8D 01 E0  STA $E001
 00:9BCD: A9 00     LDA #$00
 00:9BCF: 85 74     STA $74


The problem is that the music routine delays when you will return from NMI. On PAL there is plenty of time for it to execute before rendering begins, but on NTSC it will overlap the beginning of the frame sometimes. If this first IRQ setup doesn't happen before scanline 0, the whole screen is thrown off. (Seems to be about 10-15 scanlines late on every other frame.)

The solution should be to put this inside your NMI handler. See my last suggestion from my previous post, you should still add that CLI and RTI, but right there above the suggested CLI do this first IRQ setup right there, when you know you're still in vblank (i.e. before scanline 0) and you haven't yet run the music routine. This will allow that first IRQ to fire on scanline 0 (which will sometimes be within the music routine, but it is perfectly okay to interrupt that).


Alternative option is to put the music playback call in your main thread just after that STA $74. This will get your NMI handler returning earlier again.

Ideally both of these things should be within the NMI, though. Having the IRQs set off by the NMI will prevent them from failling if your main thread ever runs too long (slowdown), and similar with music having it in the NMI makes it slowdown resitant. However, if you can guarantee the main thread will never run long it doesn't matter either way.



Sorry for taking a long time to answer. Busy.

We'll see. I do not have much idea of ​​assembler, but let's see if I can fix this.

The routine that NMI controls is part of the NESlib library. According to the instructions that you indicate, I should put a CLI control before the JSR FamiToneUpdate line and it would look like this:

Code:

;NMI handler

nmi:

...
...
...

@skipNtsc:

   cli
   jsr FamiToneUpdate

   
   pla
   tay
   pla
   tax
   pla


This is correct?
Re: Shadow of the Beast (port)
by on (#221721)
Well, there are three things:

1. Put the IRQ setup in your NMI handler before jsr FamitomeUpdate so that it is guaranteed to happen before the end of vblank.
2. Right after the IRQ setup, put cli (also before jsr FamitoneUpdate) so that if an IRQ happens during the music routine it won't be blocked.
3. Put rti on the end of your NMI handler (after that ...tax, pla). Without this, the code just keeps running into the IRQ handler directly below.

The main thing I'm not entirely certain of, without looking at much more of the code, is whether it's appropriate to set up the IRQ every NMI or just on screens that need it. Maybe it should have a flag that turns it on and off? (When I say IRQ setup I mean that code including lines $9BBB to $9BCF in that disassembly.)

As an alternative, just as a quick test, you could just take jsr FamitomeUpdate and move it just under the IRQ setup where it is right now. (Just after where it stores a #0 to your IRQ counter variable at $74.) That would also solve the problem you're having that this music update is happening before you've prepared your IRQs to fire. I wouldn't recommend this as a permanent solution, though, because it's usually appropriate to do music in the NMI handler. If it's not in the NMI handler, music will tend to skip during scene transitions, and also you would need to manually call jsr FamitoneUpdate in each main thread frame loop if there are more than one.
Re: Shadow of the Beast (port)
by on (#221785)
Ok, let's see. Right now this is like this:

Code:
;NMI handler

nmi:

...
...
...

@skipNtsc:   
   
   LDA #$01    ; turn off MMC3 IRQ
   STA $E000
   STA $C000   ; count 20 scanlines, then IRQ
   LDA #$00
   STA $C001
   LDA #$01
   STA $E001   ;turn on MMC3 IRQ
   LDA #$00
   STA $74

   cli
   
   jsr FamiToneUpdate

   
   pla
   tay
   pla
   tax
   pla

   rti



irq:
   pha
   txa
   pha
   tya
   pha
   ldy #15            
:   dey               
   bne :-             

   ldx _Scroll_Index    
   lda _Scroll, x
   sta $2005         
   lda _scrollY       
   sta $2005         
   inc _Scroll_Index

   lda #1
   sta $e000          
   lda #14            
   sta $c000          
   sta $c001
   lda #1
   sta $e001          
   
   pla
   tay
   pla
   tax
   pla
   rti



I share the rom. It works in NES PAL and in the emulated NEStopia but now it gives problems in FCEUx and VirtuaNES.
Re: Shadow of the Beast (port)
by on (#221802)
I think the problem is right here:
Code:
 00:9BB9: 20 D8 E3  JSR $E3D8 ; wait for NMI to finish
 00:9BBC: A9 00     LDA #$00
>00:9BBE: 85 74     STA $74 = #$00 ; reset raster split index
 00:9BC0: AD C3 04  LDA $04C3 = #$04


You moved the IRQ setup into the NMI (before that CLI) but you left this reset of $74 to 0 in the main loop as soon as it returns from the NMI. I don't know what you call the variable at $74 but it appears to be an index into your table of how many scanlines to skip per split. Leaving this extra $74 = 0 in there causes the splits to start over in the middle of the screen.

Doesn't cause a problem in PAL or without music on NTSC because if NMI finishes before vblank it hasn't run any IRQs yet (resets 0 back to 0). Once you add music in, some IRQs will happen before the music is finished, and this reset ends up mid-screen.

(If I replace that STA $74 with two NOPs it seems to run as correctly as the other modes.)


Edit: Oh, you called $74 _Scroll_Index in your IRQ code, you should use that at @skipNtsc too just in case the variable ever moves. I was only calling it $74 because I was looking at it through a disassembly.
Re: Shadow of the Beast (port)
by on (#221829)
rainwarrior wrote:
Oh, you called $74 _Scroll_Index in your IRQ code, you should use that at @skipNtsc too just in case the variable ever moves. I was only calling it $74 because I was looking at it through a disassembly.


Ok, now I have understood.

According to the dougeff tutorial everything that corresponds to the IRQ configuration, etc ... is written in C, even the variable Scroll_Index I put it to 0 from there.

https://nesdoug.com/2016/01/15/24-mmc3- ... hing-irqs/

When you have indicated the faults that you see from assembler, I have not understood very well, but I let myself be guided by you until I understood it.

Well, what I have done next has been to change those two lines and put them in this way:

Code:
   LDA #$00
   STA _Scroll_Index ; ponemos Scroll_Index a 0


Now the rom seems to work well in the emulators VirtuaNES, NEStopia, FCEU, etc ...

I just need to know if it works well now in an NTSC NES.
Re: Shadow of the Beast (port)
by on (#221836)
That looks better in terms of scrolling.

One more issue though: you haven't set up 4 of the CHR banking registers. You can see the problem using Mesen, but it appears the same way on my PowerPak (i.e. the character sprite and moon sprite are using the wrong tiles). This isn't NTSC / PAL related, it is only about fully initializing the MMC3 (would look the same on PAL PowerPak/Mesen).

Of the 8 bank settings on the MMC3 (selected through $8000) I see setup for: 0, 1, 6, 7 (PPU first page, and CPU banks). You are missing any setup for 2, 3, 4, 5 (PPU second page, i.e. all your sprites).

Some emulators, and apparently the Everdrive, pre-initialize these with default values, but on the real MMC3 these are "random" when powered on. (You can see what FCEUX uses instead of randomness, for example. This seems to be a common setup pattern for emulators, Everdrive must have borrowed it.)

Anyhow, really easy to fix, just send 4,5,6,7 to the uninitialized banks 2,3,4,5 in your startup code:
Code:
lda #2
sta $8000
lda #4
sta $8001
lda #3
sta $8000
lda #5
sta $8001
lda #4
sta $8000
lda #6
sta $8001
lda #5
sta $8000
lda #7
sta $8001
Re: Shadow of the Beast (port)
by on (#221837)
The 0, 2, 4, 5, 6, 7, 0, 1 pattern seen in FCEUX MMC3RegReset() sets up an identity mapping: PPU $0000-$1FFF = CHR ROM $00000-$01FFF. It's also what my stock MMC3 init code sets up.
Re: Shadow of the Beast (port)
by on (#221902)
rainwarrior wrote:
That looks better in terms of scrolling.

One more issue though: you haven't set up 4 of the CHR banking registers. You can see the problem using Mesen, but it appears the same way on my PowerPak (i.e. the character sprite and moon sprite are using the wrong tiles). This isn't NTSC / PAL related, it is only about fully initializing the MMC3 (would look the same on PAL PowerPak/Mesen).

Of the 8 bank settings on the MMC3 (selected through $8000) I see setup for: 0, 1, 6, 7 (PPU first page, and CPU banks). You are missing any setup for 2, 3, 4, 5 (PPU second page, i.e. all your sprites).

Some emulators, and apparently the Everdrive, pre-initialize these with default values, but on the real MMC3 these are "random" when powered on. (You can see what FCEUX uses instead of randomness, for example. This seems to be a common setup pattern for emulators, Everdrive must have borrowed it.)

Anyhow, really easy to fix, just send 4,5,6,7 to the uninitialized banks 2,3,4,5 in your startup code:
Code:
lda #2
sta $8000
lda #4
sta $8001
lda #3
sta $8000
lda #5
sta $8001
lda #4
sta $8000
lda #6
sta $8001
lda #5
sta $8000
lda #7
sta $8001


I have not understood what this really does, but I have tried to fix it.

Is it right now?
Re: Shadow of the Beast (port)
by on (#221921)
Yes, this one now works on PowerPak on my (NTSC) NES with music. It also works in Mesen. The only emulator that seems to fail with it now is Nintendulator, but I'm not sure why that is.

There are smaller glitches still, I'm sure you've seen, but the main stuff is working. This is good!!
Re: Shadow of the Beast (port)
by on (#221926)
The problem this Nintendulator is the same kind of issue as with the sprites, just this time with PRG banking. You haven't initialized the bank at $8000-9FFF (banking register 6) before you use it. Apparently almost all emulators initialize this to 0, and even the PowerPak and Everdrive seem to do this too, but again this would be random on the real MMC3 cart.

Your startup code:
Code:
 03:E005: A9 40     LDA #$40 ; reset begins here
 03:E007: 8D 17 40  STA $4017 = #$00
 03:E00A: 78        SEI
 03:E00B: A2 FF     LDX #$FF
 03:E00D: 9A        TXS
 03:E00E: E8        INX
 03:E00F: 8E 01 20  STX $2001 = #$00
 03:E012: 8E 10 40  STX $4010 = #$00
 03:E015: 8E 00 20  STX $2000 = #$00
 03:E018: 2C 02 20  BIT $2002 = #$00
 03:E01B: 2C 02 20  BIT $2002 = #$00
 03:E01E: 10 FB     BPL $E01B
 03:E020: 2C 02 20  BIT $2002 = #$00
 03:E023: 10 FB     BPL $E020
 03:E025: A9 3F     LDA #$3F
 03:E027: 8D 06 20  STA $2006 = #$00
 03:E02A: 8E 06 20  STX $2006 = #$00
 03:E02D: A9 0F     LDA #$0F
 03:E02F: A2 20     LDX #$20
 03:E031: 8D 07 20  STA $2007 = #$00
 03:E034: CA        DEX
 03:E035: D0 FA     BNE $E031
 03:E037: 8A        TXA
 03:E038: A0 20     LDY #$20
 03:E03A: 8C 06 20  STY $2006 = #$00
 03:E03D: 8D 06 20  STA $2006 = #$00
 03:E040: A0 10     LDY #$10
 03:E042: 8D 07 20  STA $2007 = #$00
 03:E045: E8        INX
 03:E046: D0 FA     BNE $E042
 03:E048: 88        DEY
 03:E049: D0 F7     BNE $E042
 03:E04B: 8A        TXA
 03:E04C: 95 00     STA $00,X @ $0000 = #$F7
 03:E04E: 9D 00 01  STA $0100,X @ $0100 = #$52
 03:E051: 9D 00 02  STA $0200,X @ $0200 = #$B6
 03:E054: 9D 00 03  STA $0300,X @ $0300 = #$B6
 03:E057: 9D 00 04  STA $0400,X @ $0400 = #$4E
 03:E05A: 9D 00 05  STA $0500,X @ $0500 = #$2A
 03:E05D: 9D 00 06  STA $0600,X @ $0600 = #$84
 03:E060: 9D 00 07  STA $0700,X @ $0700 = #$2A
 03:E063: E8        INX
 03:E064: D0 E6     BNE $E04C
 03:E066: A9 04     LDA #$04
 03:E068: 20 0E E3  JSR $E30E
 03:E06B: 20 E3 E2  JSR $E2E3
 03:E06E: 20 39 E3  JSR $E339
>03:E071: 20 91 9F  JSR $9F91 ; crash occurs here!
 03:E074: 20 FD 9E  JSR $9EFD


You need to initialize banking register 6 before that line is reached. These 4 lines would do it:
Code:
lda #6
sta $8000
lda #0
sta $8001


However, it's probably a good idea to initialize all 8 MMC3 bank registers very early on in your startup code. Like I see that you've added the CHR banking initialization that I suggested but it takes place a long time after this startup routine. Might as well do all 8 in here at once. Tepples posted a suggested initial set of values to load earlier on (it's the same as FCEUX and some other emulators use, probably the same as Everdrive's initialization too).
Re: Shadow of the Beast (port)
by on (#221957)
rainwarrior wrote:
The problem this Nintendulator is the same kind of issue as with the sprites, just this time with PRG banking. You haven't initialized the bank at $8000-9FFF (banking register 6) before you use it. Apparently almost all emulators initialize this to 0, and even the PowerPak and Everdrive seem to do this too, but again this would be random on the real MMC3 cart.

You need to initialize banking register 6 before that line is reached. These 4 lines would do it:
Code:
lda #6
sta $8000
lda #0
sta $8001


However, it's probably a good idea to initialize all 8 MMC3 bank registers very early on in your startup code. Like I see that you've added the CHR banking initialization that I suggested but it takes place a long time after this startup routine. Might as well do all 8 in here at once. Tepples posted a suggested initial set of values to load earlier on (it's the same as FCEUX and some other emulators use, probably the same as Everdrive's initialization too).


Ok, it seems that now it works correctly in Nintendulator.

Yes, this technical demo contains minor errors about the scroll and the nametables.