So I'm a fan of text adventure games, and most today use an engine called a "Z-Machine" to play them. Recently, I came across the source code for a 6502 Z-machine I'm thinking of porting to the NES. I need some help setting up the programming environment.
I did little research first.
The Z-machine will be mapped using a MMC1 - in an SNROM or SUROM config (Perfect world, SXROM would be good, more on that later.)...
The idea is that the Z-machine kernel will reside in $C000-$FFFF
Here's where it gets kind of dicey.
A Z-machine is, for all intents and purposes, an emulator, and the actual story file will be embedded in the ROM. The kernel will bank in chunks of the story file at $8000-$BFFF and run the z-code there, when runs to the end of the page, (Or jumps to another part of z-code) then that section is banked in. Console based z-machines have been made in the past. There is one for the original Gameboy. You would have a ROM "stub" that you appended the story file to the end and then flash the whole thing to a cart. I'm thinking of doing the same thing with the NES version.
I would love to use a memory config that would allow me the most ROM and RAM, MMC1 seems the easiest and most supported if I actually want to make a cart. Having a 512K story file accessible would be awesome, but you can do a lot with 256K. Maximizing memory would be cool too, but I can live with 8k plus the zero page.
I need to know how to properly set up an environment to start porting this, or any ideas on other memory mappings that might be better. I looked at an snrom template, but that was too complicated for what I needed. (That and when I tried to compile it under windows it failed). I just need something that generates a "blank" ROM that has the iNES proper header, vectors set up, and ORG set to $C000. That way I can concatenate the story file at the end of the ROM as data.
Oh and text input would either use the NES keyboard, or an on screen equivalent.
Thoughts and assistance?
ROM memory is relatively cheap regardless size. You don't save/spend many cents between 256k, 512k, or less/more.
You should also take a look at
GTROM (available through memblers) or
Mapper 30 (available through InfiniteNESlives) - both affordable, generous, popular homebrew mappers.
If you want people to play the game, i advice against designing the game around NES keyboard input. It could always be an add-on nicety, but it's just too rare.
Just in case: If the engine you found is using decimal mode anywhere, you will want to rewrite those sections since decimal mode was removed from the NES version of the 6502.
GTROM looks cool, but I need a bank window for the z-code. That seems to bank in the whole 16K bottom. Also I'm planning on developing using FCEUX because of it's really cool looking debugging tools. I need to make sure the mapper is supported. It says that UNROM 512 is supported by FCEUX r3071 and I can only find version 2.2.3 - r1600(?) Is there something newer? Maybe another emulator with a debugger maybe No$nes is better?
I still need a little help setting up the environment regardless.
Quote:
I came across the source code for a 6502 Z-machine
I support this project.
But...
text only seems to be a misuse of NES capabilities. Personally, I would add some kind of graphics. It's your project though, don't let my bias ruin it.
See my previous comment on your project idea...
viewtopic.php?f=5&t=17146&p=215194
FrankenGraphics wrote:
You don't save/spend many cents between 256k, 512k, or less/more.
This is slightly off topic, so I'll just say this and stop:
For a simple mapper, Greenliant and Microchip sell 5V Flash in sizes ranging 64 KiB through 512 KiB, for prices around 0.8 - 1.3 USD per in qty 100.
Larger memories are available, but there's a significant cost bump from 512 KiB to 2 MiB.
—
dougeff wrote:
text only seems to be a misuse of NES capabilities. Personally, I would add some kind of graphics.
There's a tool on smspower forum to convert Twine games to the SMS. It even supports limited graphics.
dougeff wrote:
Quote:
I came across the source code for a 6502 Z-machine
I support this project.
But...
text only seems to be a misuse of NES capabilities. Personally, I would add some kind of graphics. It's your project though, don't let my bias ruin it.
See my previous comment on your project idea...
viewtopic.php?f=5&t=17146&p=215194Oh! Z-Machine is an
open standard, and the
6502 code I have is on the MIT license. You can make your own Z-Machine game using
Inform 7There is a lot oh ho-humming about the input system. There are lots of console text input systems for text adventure games. I have played many in the past. (On both Japanese and English) They are super intuitive and do more than just pop a keyboard on the screen.
Thanks for all the mapper ideas, but, like I said, I'm limited to what's available via emulation first. I don't own an NES as of right now and I don't want to invest in hardware unless my idea proves feasible. This means I'm limited to mappers that are supported by emulators with robust debugging functions.
What's really stymied me now is getting an environment set up in windows so I can have ca65 (well, actually ld65) spit out a proper rom. I'n new to to the NES scene, but *VERY* old hat to 6502. (My wheelhouse is reversing Apple II games). I'm very used to creating .s file with a ORG at whatever the entry point is and have it spit out a binary blob. The NES is strange as I have to make the linker spit out a proper rom. (With lots of blank filler pages). I'm going though the ld65 docs now. but it's a but vague on the -t nes option Like I said, the SNROM template is much too complicated for what I'm trying to do, with all it's includes and such. I'm porting a monolithic .s file
In a perfect world having a simple 5 or 10 line .s file with just the vectors and an ORG directive, along with the proper linker arguments would help. (By all means keep the mapper advice coming!)
Quote:
it's a but vague on the -t nes option
It doesn't do anything useful.
Only if you use cc65 c compiler, and include... conio.h/conio.c or time.h or nes.h... does it do anything.
which I wouldn't use any of these.
It does do something useful. The default is c64, which uses some weird encoding instead of ASCII. That can in some situations corrupt/break your embedded text.
Quote:
GTROM looks cool, but I need a bank window for the z-code. That seems to bank in the whole 16K bottom.
Technically GTROM doesn't split the 32kB program window at all. What memblers' tool does is interleave, at your option, a segment of code as if it was a fixed 16k bank by copying it at the same adress to all 32kB banks. This is a configuration out of convenience and tradition, but using your own configuration in ld65 you could make the "fixed bank" segment any size you'd like - 8kB:s, 6kB:s, 5321 bytes... anything you might want; doesn't matter.
Actually, you can do this with
any 32kB swappable bank mapper, not just GTROM, which may open some options for you. The drawback is the sacrifice of rom space of course. With membler's tool, you'd be reducing the 512kB:s to 256 effective kB:s. With an 8kB fixed bank, you have 384 kB:s at your disposal. And so on. It's quite versatile though in that you can tailor the "fixed" bank to be exactly as large as your program, which means you can keep a lot of data visible at the same time.
Yeah, GTROM hasn't made its way into vanilla FCEUX yet, you need to use an interim build or memblers' fork, listed on the wiki page. Else, i think only Mesen and PowerPak (a virtual cartridge), as of novasquirrels' contribution, supports it. Mesen supports all features (well, except the on-cartridge LED controls of course), and is overall great as a developer/debugging tool.
@lidnariq, ah you're right, i remember there was a bump between 512kB and the next tier. iirc, that evens out once you go even more upwards, provided the mapper can support it. But then we're talking about amounts of storage you'd probably only need for streaming audio or video or make a DOS-like point and click adventure game with loads of unique graphics.
halkun wrote:
I still need a little help setting up the environment regardless.
I'd be willing to add support for mapper 111 GTROM to
nesicide. Have you considered it? I have a basic "Hello World" template in asm available in the IDE that sets everything up for you and even...wait for it...prints Hello World to the screen.
(ot, but fwiw project blue is managed from nesicide and was at a point targeting gtrom. it's just that we're currently using a similar mapper (edit: BNROM) that more emulators accept since we we're not using any exclusive gtrom features for this game).
edit for claritfication.
Quote:
The default is c64
No. The default is NULL, which indexes in the target enum to TGT_NONE, which sets target as "none" and target CPU as CPU_6502.... and sets the character map to "CTNone" which is the same character map that is set if NES is target.
I don't see anything in the source code which makes me change my opinion.
https://github.com/cc65/cc65/blob/153bb ... n/target.hhttps://github.com/cc65/cc65/blob/153bb ... n/target.c
Just a warning: You may need a good bit more than 8 Kbytes of RAM. How much depends on the game, common might be something like perhaps 12..30 Kbytes for the game state, plus about as much memory for each savestate.
Most of the RAM is initialized by copying initial data from ROM, the gameboy version redirects all RAM reads to the initial ROM values - unless the RAM content was changed.
With that trick, it does require only "0 bytes" of RAM when the game starts, but eats up 3 bytes per changed RAM location (for storing address and data). I have got several bug reports saying that the Hitchhiker's Guide is quickly running out of memory.
Z-Machine has it's own text encoding so there is a translation layer to ASCII anyway. Note that Z-machine was designed in 1979 for minicomputers. There's a version for the ZX Spectrum that little guy only has 16K of ram and a tape loader. "Out of the Box" the NES has enough resources to run a Z-Machine engine.
Zeugma, the 6502 engine I found, has lots of C64 dependencies, but that is for input, output, and storyfile storage. The Z-machine engine can be reduced down to String input, and text line output. and everything else is internal. There will be a bit of cleaning out of Zeugma to get the NES hooks in. The means the screen will be a 28x30 text display and not the fancy bit mapped one from the C64 version. Maybe I'll use PPUSCROLL to scroll the text, but I want to use the second nametable for the text input system.
Heck, my first Z-machine game I ever played was on a Tandy Color Computer 2 and that didn't even have lowercase letters
Nesicide looks cool, but there isn't a Windows version. The download link is broken. Shame as that looks really promising!
Looking at nocash's warning (HI! BIG FAN! LOVED YOUR PSX WORK!!!!) maybe memory banked ram too? Zeugma has a virtual ram system in it I can borrow. I hope I'm not crawling out of realm of feasibility,
Both UNROM 512 and GTROM can self-flash, provided your writer routine runs from internal RAM. You can treat the whole 512kB chip as a persistent RAM of sorts. You just want to avoid writing to fROM continously during program. User triggered, spread out stage changes in a text/turn based game is not a problem.
btw, not that this is unique to the NES, but one of the design problems with keeping lots of text in a tile graphics game is that reading monospaced glyphs is fatiguing. But there's plenty of space to add adjusted small letters. This example only has a few common adjustments - i had another more worked-through proof of concept but it i can't find it for the time being. At least this shows that you can have a fairly detailed font and symbol set and still have room for decorative graphics, even without chr banking tricks.
Years back, when tpw_rules was trying to make a Z-machine interpreter, I wrote a terminal library that uses interrupts and palette trickery to make a full-screen VWF plane. (See
previous topic.) But if you're using one of the low-cost boards (UNROM 512 or GTROM), this won't work unless you're willing to do some deep DMC magic.
Will this require the Subor keyboard?
halkun wrote:
Nesicide looks cool, but there isn't a Windows version. The download link is broken. Shame as that looks really promising!
Thanks for pointing that out!
I've been trying to get a Travis Windows CI deployment set up but it's new for them so isn't working just yet. In the excitement of it all I accidentally blew away the images I'd put up manually. I'm resurrecting my Windows VM now and should have a manual Windows build back online from that in a few hours.
As a wait on the windows Nesticide upload, I'm still looking at the different mappers. MMC5 has banked switched RAM, but what other ones have that ability?
So looking around it appears I need a mapper that can.
1) Bank out one half of the ROM. One fixed bank for the Z-Machine Kernel and one bank for the story file.
2) The ability to bank out the 8K RAM - I need at least 16K, but I guess 32K would be great
3) The mapper needs to be supported by an emulator with a debugger
From the looks of it SXROM would be my best bet as it seems I can buy repo boards from infiniteneslives.com and it allows for 512KB of ROM and 32KB of RAM I'm checking the MMC1 page and it appears that actually doing the bank switching is a little strange, but I'm sure with a few experiments I'll figure it out.
Now I need to figure out how to make ld65 spit out a generic, empty SXROM image.
halkun wrote:
MMC5 has banked switched RAM, but what other ones have that ability?
Commercially, it's only MMC5 and some MMC1 variants (SXROM , SOROM, SZROM ).
Recently we observed that FME-7 is physically capable of it, but emulator support isn't particularly widespread.
When/if you get as far as making hardware, we could design inexpensive things that would support multiple banks of PRG RAM.
Using an MMC5 for text games seems like overkill to me...
halkun wrote:
Now I need to figure out how to make ld65 spit out a generic, empty SXROM image.
snrom-template gets you halfway there; you just have to change the header to NES 2.0.
dougeff wrote:
Quote:
The default is c64
No. The default is NULL, which indexes in the target enum to TGT_NONE, which sets target as "none" and target CPU as CPU_6502.... and sets the character map to "CTNone" which is the same character map that is set if NES is target.
https://github.com/cc65/cc65/blob/maste ... in.c#L1434Apparently cl65 and cc65 have different defaults.
That, I didn't know.
This inconsistency seems like a bad idea, maybe someone should do a pull request?
tepples wrote:
halkun wrote:
Now I need to figure out how to make ld65 spit out a generic, empty SXROM image.
snrom-template gets you halfway there; you just have to change the header to NES 2.0.
I wasn't able to get this to compile under Windows. I'll give it another shot and tell you the error I'm getting.
Good luck with the template. That looks huge. I've always manually defined the 16 header bytes.
Banked RAM might be required, especially if a game requires more than one bank for the current game state (without even thinking about save states). Using FLASH for savestates would be also fine - but you could think about that later.
Which mapper to use isn't so important, you could probably easily change it later once when the game is working. As long as you stick with a central bank switching function/macro, or at least use some symbolic constant for the mapper I/O registers.
MMC1 requires five writes to change a 5bit register. MMC5 needs only one write, so that would be faster. And MMC5 might be more common & more widely supported for large memory. But either one should be fine for getting started.
halkun wrote:
As a wait on the windows Nesticide upload, I'm still...
I haven't had someone call it nesticide since a former coworker decided that was what I was saying.
I had some troubles with my Windows VM yesterday. So I'm currently attempting to build on a native Windows laptop.
WRT the SNROM template, I had put a
nesicide project based on it up on my google site *long ago*.
I will try compiling that once I get a Windows build and report back.
Looking at the makefile, I think I know what's wrong under Windows: the Python executable on the PATH is called
py.exe, not
python3.exe. When I discovered this, I changed the makefiles of a lot of my other projects to compensate for this using an
ifdef COMSPEC clause to detect the host OS, but I had missed snrom-template. Commit
4f11fad should fix it.
tepples wrote:
Looking at the makefile, I think I know what's wrong under Windows: the Python executable on the PATH is called
py.exe, not
python3.exe. When I discovered this, I changed the makefiles of a lot of my other projects to compensate for this using an
ifdef COMSPEC clause to detect the host OS, but I had missed snrom-template. Commit
4f11fad should fix it.
I just googled for something equivalent to this and found:
Code:
OSTYPE=`wmic os get osarchitecture`
if [[ $OSTYPE =~ .*64*. ]]; then
...
fi
nocash wrote:
And MMC5 might be more common & more widely supported for large memory. But either one should be fine for getting started.
Quoting INL:s shop page:
Mapper 5: MMC5 ExROM
A simplified version that supports large memories of MMC5 may be possible with current boards. Full fledged version pending an entire new PCB design.
So not quite as readily available as MMC1. Either way, you could ask for a quote.
The full MMC5 is much more than you need, but a subset that just handles banking of PRG RAM should be cheap.
The only downside to targeting an MMC5 subset is that a third party seeking to make a hardware reproduction may think they have to destroy an original cart instead.
So either way, set it up so that the part of your code that deals with the cartridge hardware can be easily replaced. Novel hardware can easily be designed once you know everything you need.
halkun wrote:
Oh and text input would either use the NES keyboard, or an on screen equivalent.
Both software keyboard and the Family BASIC keyboard support would be desirable (and maybe Subor keyboard for famiclone people). Family BASIC keyboards are common and dirt cheap nowdays, but NES people would need an ENIO-like adapter.
I have worked on Famicom Z-machine implementation some time ago, although I have since stopped (I have not bothered to install the software on this new computer, which is Linux rather than Windows). Here is a link to some further information:
http://wiki.nesdev.com/w/index.php/User:Zzo38/Famicom_Z-machine Maybe some of this might be found to be useful for your NES Z-machine.
Neat! Another Z-machine to poke at!
I've got my environment almost set up. I'm going with a SXROM but having issues getting an emulator to take my header.
I'm going with a 512K PRG-ROM with 32K PRG-RAM and an 8K CHR-ROM
My header looks like this
Code:
.byte "NES",$1A ; "NES"^Z
.byte $20 ; 4 - ines prg - Specifies the number of 16k prg banks.
.byte $01 ; 5 - ines chr - Specifies the number of 8k chr banks.
.byte %00010001 ; 6 - MMC1 and vert mirror
.byte %00001000 ; 7 - nes2.0 header
.byte $00 ; 8 - ines map - Specifies the NES mapper used.
.byte $00 ; flags 9
.byte $00 ; flags 10
.byte $00 ; flags 11
.byte $00 ; flags 12
.byte $00 ; flags 13
.byte $00 ; flags 14
.byte $00 ; flags 15
and my nes.ini config file I'm feeding into ld65 with -c looks like this.
Code:
MEMORY {
ZP: start = $0, size = $ff, type = rw;
HEADER: start = 0, size = $0010, type = ro, file = %O, fill=yes;
RAM: start = $0300, size = $0500, type = rw;
ROM00: start = $8000, size = $4000, type = ro, file = %O, fill=yes, fillval=$FF;
ROM01: start = $8000, size = $4000, type = ro, file = %O, fill=yes, fillval=$FF;
ROM02: start = $8000, size = $4000, type = ro, file = %O, fill=yes, fillval=$FF;
(They repeat here... you get the picture)
ROM31: start = $C000, size = $4000, type = ro, file = %O, fill=yes, fillval=$FF;
}
SEGMENTS {
INESHDR: load = HEADER, type = ro;
ZEROPAGE: load = ZP, type = zp;
BSS: load = RAM, type = bss, define = yes, align = $100;
DMC: load = ROM31, type = ro, align = 64, optional = yes;
CODE: load = ROM31, type = ro, align = $100;
RODATA: load = ROM31, type = ro, align = $100;
VECTORS: load = ROM31, type = ro, start = $FFFA;
}
FILES {
%O: format = bin;
}
I also have a 8k char file (It has the text) I append to the end of the .NES file with a copy /b command
Both NO$NES and FECUX are telloing my header is invalid
What's the proper format?
Also is there a way to "include" my char rom at compile time so I don't need to append it with a copy command afterwards?
halkun wrote:
32K PRG-RAM
[...]
.byte %00001000 ; 7 - nes2.0 header
.byte $00 ; 8 - ines map - Specifies the NES mapper used.
.byte $00 ; flags 9
.byte $00 ; flags 10
You're not succeeding at making the right header there
You need to specify the amount of PRG-RAM (i.e. WRAM). Also, I don't think SXROM was ever used with CHR-ROM in commercial releases, so emulators might be rejecting your ROM for not using a standard configuration. Try with CHR-RAM (i.e. 0 CHR-ROM pages) and set the size in byte 11 to see if that changes anything.
As for including the CHR file during assembly time, sure, you can use the .incbin directive, but you have to create the corresponding MEMORY and SEGMENT definitions in your config file to hold that data. Not that you'd be doing this for CHR-RAM, of course.
halkun wrote:
I also have a 8k char file (It has the text) I append to the end of the .NES file with a copy /b command
...
Also is there a way to "include" my char rom at compile time so I don't need to append it with a copy command afterwards?
Example for 2 CHR-ROM banks:
Code:
ld65 config:
MEMORY {
; ...all your existing stuff (ex. ZP, RAM, header, PRG banks)...
;
CHR00: start = $0000, size = $2000, type = ro, file = %O, fill = yes, fillval = $00;
CHR01: start = $0000, size = $2000, type = ro, file = %O, fill = yes, fillval = $00;
}
SEGMENTS {
; ...all your existing stuff...
CHR00: load = CHR00, type = ro, define = no;
CHR01: load = CHR01, type = ro, define = no;
}
somewhere in your code (ex. main.asm or whatever):
.scope CHR00
.segment "CHR00"
.incbin "chr00.chr"
.endscope
.scope CHR01
.segment "CHR01"
.incbin "chr01.chr"
.endscope
You can omit the
.incbin line if you want to make a CHR bank filled with nothing but zeros (i.e. placeholder for future CHR files); the ld65 config will take care of filling the space with zeros (
fill = yes, fillval = $00).
It's still up to you to make sure your header etc. refers to the correct number of CHR banks (should always be a 2^n number, ex. 1, 2, 4, 8). Same goes for PRG.
fillval = $00 or
fillval = $ff can be used (I recommend the former for debugging/testing, then before final release switching to the latter (to be nicer on EPROM/EEPROMs) but it really doesn't matter since people aren't making mask ROMs of homebrew).
If your mapper uses a CHR-ROM bank size that differs from the 8KByte header size (ex. MMC3 using 1KByte or 2KByte CHR banks), then things get a bit more complicated. There's multiple ways to solve this, but I'd suggest keeping
size = $2000 (to ensure the resulting ROM file gets 8KByte CHR, per the header requirement), then using multiple
.incbin statements within the appropriate scope/segment area. You may have to refactor the code a little bit here if you want to dynamically calculate CHR bank number. Others here might have some advice on how to do that; if their recommendation differs from mine, follow what they say instead.
Cool, I got the CHR-ROM appended, but it's still rejecting my header
Code:
.byte "NES",$1A ; "NES"^Z
.byte $20 ; 4 - ines prg - Specifies the number of 16k prg banks.
.byte $01 ; 5 - ines chr - Specifies the number of 8k chr banks.
.byte %00010011 ; 6 - MMC1 and vert mirror + SRAM
.byte %00001000 ; 7 - nes2.0 header
.byte $00 ; 8 - ines submap.
.byte $00 ; flags 9
.byte %0001001 ; flags 10 ; 10 - 32K PRG-RAM
.byte $00 ; flags 11
.byte $00 ; flags 12
.byte $00 ; flags 13
.byte $00 ; flags 14
.byte $00 ; flags 15
When I run the NES Mapper program, I get this...
So it looks OK....
and the error I get in FECUX is "FDS BIOS ROM image missing"
no$NES say "invalid cartridge header" and just exits
One inconsistency I see there is that you marked the battery-backed WRAM bit, but the amount of battery-backed PRG-RAM below is 0. Do you need it to be battery-backed or not? Either clear the battery bit or specify the 32KB of PRG-RAM as battery-backed.
That being said, I find it very weird that FECUX brought the FDS into this...
Do NO$NES and FCEUX support NES 2.0 headers? FCEUX will throw said error message
if the NES header is omitted or ROM identifier string is wrong.
That said, I notice this in your screenshot of whatever that GUI tool is:
CE C5 D3 1A 20 01 ...Those first 3 bytes are not "NES" (that would be 4E 45 53), and they're outside of the ASCII range -- all of your string-based bytes have bit 7 set for some reason! However, they are all the "correct deltas" from one another. Could this potentially be a locale/code page/character set problem, where string
"NES" is somehow being moved into a non-ASCII region? I clearly see
.byte "NES",$1A in your code, but obviously something is stomping over that with some other data, or something is being assembled oddly.
Try replacing
.byte "NES",$1A with
.byte $4E,$45,$53,$1A and see if that helps. I bet it does. If it does, you're going to need to figure out what's causing this oddity (setting bit 7 of your strings), as that's probably going to cause you problems.
Other oddities I see:
- MEMORY section, ZP:
size = $ff is wrong, ZP is 256 ($100) bytes, not 255 ($ff) bytes.
- MEMORY section, RAM:
start is at $0300, while actual RAM starts at $0200 (and is thus $600 bytes in size). If this is intentional, then ignore this
- SEGMENTS section, HEADER: try adding
align = $10I would also suggest, when linking your program with ld65, using
-m map.txt and then looking at its contents when finished. e.g.:
Code:
ca65 main.s
ld65 -C ld65.cfg -m map.txt -o game.nes main.o
koitsu wrote:
Those first 3 bytes are not "NES" (that would be 4E 45 53)
... revenge of PETSCII.
viewtopic.php?p=233224#p233224
lidnariq wrote:
koitsu wrote:
Those first 3 bytes are not "NES" (that would be 4E 45 53)
... revenge of PETSCII.
https://forums.nesdev.com/viewtopic.php ... 24#p233224Ah ha. So it sounds like further CPU configuration is incorrect in the assembler. Would
.setcpu "6502" at the very top of the main code (i.e. before the header segment) rectify this? The ca65 documentation implies doing this can "override" whatever
-t/--target is, which defaults to
none but maybe not in this case?
-t nes would ideally work too, I think. The OP has not reported what arguments they're using to ca65/ld65.
Edit: oh, I see.
cl65 defaults to a target type of
c64, which I think would cause this problem (see
PETSCII chart); while
ca65 defaults to a target type of
none. I didn't know cl65 was being used here. Best to use
-t nes to either utility.
It was the PETSCII - I got no$nes to load the file (FCEUX - not so much, but it's a start) Sadly, that means the .byte psudo-op is useless for text
I can't use -t nes because I'm using -C for my config file and you can't use both at the same time. I could simply put the CHR-ROM in PETSCII order, but I'd much rather use ASCII
Also, no$nes sees all 512KB of PRG-ROM, but not too sure on the PRG-RAM, I may need to tweak the header further.
==EDIT==
cl65 does allow "-t none -C file.ini" at the same time and I have my precious ASCII table back.
You can also use the .charmap directive to map the characters however you want.
That's cool. I have my functional template up now. I'm still have questionable PRG-RAM, but that is another battle for later.
Now to study the PPU so I know what exactly I'm doing...
If worst comes to worst, I at least have an MMC1 setup I can revert to more sane numbers and do something a little less ambitious if the Z machine thing turns into a mess. Better yet find some other 6502 game to port. I'll look around.
I would be surprised if I have had added support for banked MMC1 RAM in no$nes (in everynes.htm it's still marked as reportedly existing, but unknown it works).
PS. Congrats on the first text output.
I know, the worst thing would be I'll be stuck with 8K.
Well, I mean the *worst* thing I can do is break your emulator with a non-standard mapping configuration and then submit a bug report
There are other 6502 ideas rolling around though.
For now I'm keen on streamlining the text display, Who knows, if Z machine is too complicated, I can revert to an old school text adventure with a graphic on the top and text on the bottom, and parser with less verbosity. I'll have to use CHR-RAM then.
With the template figured out I can go anywhere with this.
Hmmm
It would seem that assigning more that 8K of ram is problematic for emulators, so I think I'll scale back a bit
I made it a 512K ROM with 8K save ram
Sadly, it only opens in no$NES
All the other emulators I'm trying are attempting to load bank 00 and 0F (That has nothing) I thought emulators loaded the last bank and the first bank so it should be loading 00 and 1F.
Is there some kind of compatibility thing I'm running into?
MMC1 cannot load 16K banks from disjoint 256K sections simultaneously. The MMC1 was only designed to give you 256K PRG originally, and
a dirty hack was employed to increase this amount to 512K.
If no$nes lets you do that, even gives you it by default, that's a bug.
So MMC1 can't do 512K either?
MMC1 can do 512K if you're willing to deal with the hack.
That hack involves selecting between two 256K halves at run time.
MMC1 supports 512KB but in a hack-ish way. It's not guaranteed to work on every emulator. It's up to you to decide if it's worth it.
Even if you do get it working -- which is possible -- you have to design your code to work off of the 256KB limit. That is to say: the final hard-wired PRG-ROM bank will be the last 16KB bank of the first 256KB half. At run-time, you can "swap" between which 256KB "half" you want to use -- but at boot-time the hard-wired half is always the first half.
In short: MMC1 was never designed "from the ground up" to support >256KB. MMC3 (mapper 4) can provide that, or other mappers like UNROM-512 (though you will not get PRG-RAM support on that mapper). In other words: you're going to have to work with these design quirks, you can't fight it.
https://wiki.nesdev.com/w/index.php/MMC1 has the details. The 512KB "quirk" (for switching 256KB halves) is under
https://wiki.nesdev.com/w/index.php/MMC ... Mapper_001Otherwise, MMC3 has 512KB support natively, and does support PRG-RAM (8KB).
Large-ish PRG-ROM is generally not a common thing; console mappers etc. were really not designed for it. 256KB was considered quite large for the time. Please step back and think about the era/time frame of the system you're working on. :-)
koitsu wrote:
but at boot-time the hard-wired half is always the first half.
Should be random, not bottom half.
lidnariq wrote:
koitsu wrote:
but at boot-time the hard-wired half is always the first half.
Should be random, not bottom half.
Oh, I didn't realise the internal state of the bit in the mapper would essentially be random. Yikes.
In that case, the solution is obvious: ensure in your ROM that the upper 16KB PRG-ROM bank (of the first and last 256KB halves) are identical, i.e. 16KB PRG-ROM bank $0F and $1F need to be the same. ld65 should make this easy, and the classic
copy /b prg00.bin+prg01.bin+... method should be fine too.
Right-o 256K + 8k SRAM it is
I'm going to reevaluate my project then as that's too small to fit the Z machine I want. Good news is that I fought so far to get a working template, might as well do something with it
I'm looking up some really old 6502 game books and see if something catches my fancy
==EDIT==
OH! *THATS* how they crammed FF1 and FF2 on the same cart... OK...
Why do you want to give up here? Now that you have your header/template working, you could as well change it to MMC5, which should be easiest and most straight forward for large memory.
For MMC1, if you want your code in "last bank", you would have to store the code in "both last banks" (of each of the 256K-halves), that's making it a bit more difficult to merge code + game data, but it isn't impossible to do.
But when chosing between MMC1 and MMC5, I really think that MMC5 would be better for ease and speed and compatibility.
nocash wrote:
But when chosing between MMC1 and MMC5, I really think that MMC5 would be better for ease and speed and compatibility.
It's not better for distribution, though... But I guess that depending on the subset of MMC5 features you actually need, you might be able to find someone who can publish your game.
Well, I'm new to NES development, and learning new and partially documented mappers are tricky. MMC1 is really straightforward So it's always better to scale back and not biting off too much. Anyways, limitations spur creativity, and I've been in little boxes before. I'm building up a little kernel and getting an NMI loop going. I'm not out of ideas. For fun I was wondering if I could do some "race the beam" kind of things with the NES, but that is going to require real hardware. On the Atari 2600 you could count cycles and alter the scan line while it's drawing on the phosphor. Looks like on the NES you are not even allowed to monkey with the beam during HSYNC. (or even detect it for that matter) I was contemplating if you could update the nametables during HSYNC and have it spit out a different pattern for that line. If you can update the nameable on each line, you can have a full screen bitmap. Like I said, I wouldn't even know how to detect when the beam is in HSYNC so I can play with the PPU while it's off.
I'm occupying myself with a psudo NES "Text mode" anyway. Still leaning on text adventure game. But Z machine is too strong (I wanted to run v8 games) Actually, having the compiler stuck in "PETSCII" mode gave me some ideas.
halkun wrote:
Looks like on the NES you are not even allowed to monkey with the beam during HSYNC.
Some things are off limits, but some things are still available. For example, color emphasis, the monochrome bit, and bankswitching registers are all possible and have contemporary examples.
Quote:
if you could update the nametables during HSYNC and have it spit out a different pattern for that line.
The
contents of the nametables, no, but you can adjust the exact location out of all possible available nametables.
halkun wrote:
For fun I was wondering if I could do some "race the beam" kind of things with the NES, but that is going to require real hardware. On the Atari 2600 you could count cycles and alter the scan line while it's drawing on the phosphor. Looks like on the NES you are not even allowed to monkey with the beam during HSYNC.
Pixel-level synchronization on the NES is notoriously tricky, and even in the best possible scenario you'll still get a couple pixels of jitter...
Quote:
I was contemplating if you could update the nametables during HSYNC and have it spit out a different pattern for that line. If you can update the nameable on each line, you can have a full screen bitmap. Like I said, I wouldn't even know how to detect when the beam is in HSYNC so I can play with the PPU while it's off.
To access VRAM during display time, you need to turn rendering off, and one side effect of that is that it compromises the sprites for one scanline. Also, the hblank period is so short, that there there's barely enough time to update a single byte in VRAM, since you need to turn rendering off, set the VRAM address, write the data, reset the scroll and turn rendering back on.
There are other kinds of raster effects that are much easier and safer to perform though, such as scroll changes, pattern swaps and color emphasis/grayscale.
A full screen bitmap can be achieved fairly easily in 1bpp (i.e. 2-color) with some palette trickery and a pattern table swap halfway down the screen. A regular 2bpp full screen bitmap will require more CHR memory, either RAM or ROM.
You don't have much CPU time in HBlank. 6502 instructions average ~3 cycles each (consider: a ZP load followed by a PPU write takes 7 cycles). Switching CHR-ROM banks is certainly possible, or doing a couple PPU register tweaks, but that's about it. Usually this is only something considered if there are truly justified needs for it.
If your goal is to do text-based adventures, HBlank is the least of your concerns/worries right now -- not to tell you how to run your project or anything... HBlank effects are considered highly advanced material; I don't think many here on the forum have spent much time doing it either. On the flip side,
demos like this are possible, but consider that entire piece of work is precisely-timed (read: cycle counting) and IIRC, really doesn't leave much CPU time for doing other things within reason.
I think as you get more and more into this project of yours, you're going to realise that understanding the design/model and specifications (plus implementation/usage model) of the NES is going to strongly dictate what you can accomplish. Don't forget: people like myself didn't enjoy Zork because of fancy graphics or effects.
tokumaru wrote:
There are other kinds of raster effects that are much easier and safer to perform though, such as scroll changes, pattern swaps and color emphasis/grayscale.
Here are a few examples of cool effects on the NES that are possible with combinations of the techniques I mentioned before:
https://youtu.be/BegOGJFePv4?t=0 (title screen in F-FF)
https://youtu.be/XVbZAPBPwZY?t=998 (3D floor in Cosmic Epsilon)
https://youtu.be/dWHPNnrTmKs?t=2185 (overlapping background layers in Bucky O'Hare)
https://youtu.be/43pmwBwBoHs?t=32 (semi-transparent water in Noah's Ark)
https://youtu.be/_GSfLqJUcOM?t=60 (multiple parallax layers with overlap in Sword Master)
https://youtu.be/bukusPiWTmU?t=438 (perspective floor in Battletoads & Double Dragon)
https://youtu.be/V6ngD3ZC1z8?t=594 (roads with hills in Rad Racer)
https://youtu.be/nfY79-3AdGY?t=152 (psychedelic background in Recca)