Page 1 of 1

NES to SNES - JML/JSL/Bankswitching - Myth Help/Assistance!

Posted: Tue Aug 30, 2011 12:51 am
by Hamtaro126
Yes, It is another wierd-arse question, but in order to use banks for SNES, we need to use long jumps,

We need to figure out a myth concerning conversions, at least with some compare routines, using the rom and extra SNES RAM for the bankswitch emulation.

Games like Hebereke and SMB2 have bankswitching, I just turned the banks into 32k (16k combined with Fixed Bank).

In short: Can/Did anyone solve this big myth?

EDIT: Tables are also what I am talking about, Can't always do it without a way to find the bank switching tables.

Hebereke uses some sort of them. But I do not know...

Posted: Tue Aug 30, 2011 4:26 am
by d4s
The way you stated your question is vague and I don't really get what the myth you're talking about might be.

Here's how I understand it:
You want to port NES games to the SNES and you have a problem rewriting the PRG-ROM bankswitching parts to work on the SNES.

I started to port a NES game myself a while ago (just to check out how much work would be involved), and found that the hardest/most tedious parts were getting a 100% accurate disassembly (which i consider imperative) and rewriting PPU register accesses.
The game I worked on used 8kb CHR-RAM, which spared me the trouble of CHR-bankswitching, which (depending on the game) could obviously implicate heavy rewrites.

Didn't have a single problem rewriting the bankswitching code to use long jumps instead.
Please elaborate on what exactly is causing you trouble.
Code examples would help.

Posted: Tue Aug 30, 2011 10:39 am
by Hamtaro126
d4s wrote:The way you stated your question is vague and I don't really get what the myth you're talking about might be.

Here's how I understand it:
You want to port NES games to the SNES and you have a problem rewriting the PRG-ROM bankswitching parts to work on the SNES.

I started to port a NES game myself a while ago (just to check out how much work would be involved), and found that the hardest/most tedious parts were getting a 100% accurate disassembly (which i consider imperative) and rewriting PPU register accesses.
The game I worked on used 8kb CHR-RAM, which spared me the trouble of CHR-bankswitching, which (depending on the game) could obviously implicate heavy rewrites.

Didn't have a single problem rewriting the bankswitching code to use long jumps instead.
Please elaborate on what exactly is causing you trouble.
Code examples would help.
I changed my mind... I was going to do SMB2, But appearently it's not that good to do it!

I guess I'll create a new SMBDIS package (Easier).

Since no CA65 SNES code for GFX and other stuff exists, I had to try to create a new NES Emulation method. (Sound is at least MSU1 Only for now.)

I already know how to disable sprite 0 for it, as the SNES PPU cannot use it.

the SMB Disassembly is by Doppleganger and can be found in RomHacking.Net.

EDIT: If you have the code for your NES Port, Can you please share? (Without the actual game code, of course.)

Posted: Fri Sep 02, 2011 7:37 am
by d4s
Hamtaro126 wrote: EDIT: If you have the code for your NES Port, Can you please share? (Without the actual game code, of course.)
Yeah, in case this ever yields something presentable, I'll release the full sourcecode.

Regarding the topic of bankswitching and long jumps:
IMHO, the only correct way to do this is to replace all instances of bankswitching with native long jumps, i.e. remove all traces of the bankswitching interface.
This requires quite some effort, mainly because you'd not only have to modify all callers, but all callees aswell.


If, for some reason, you'd want to take the route of least possible modification,
preserving the bankswitching interface, possibly using static patches even (which probably would be a gigantic nightmare to maintain), the following would be one possible way to do that.
It's far from pretty though:

original nes bankswitching code, AOROM game:

Code: Select all

/**
* switch bank, jump to subroutine
* 
* @param a	return bank with mirror flag
* @param x	(target routine number + 1) * 3
* @param y	target bank with mirror flag
*/
Lbl_00_ffcd:
	ora #$00
	sta $2d
	lda $13
	pha 
	stx $13
	lda.w AOROM_BANK_PPU_MIRROR_2000,y
	sta.w AOROM_BANK_PPU_MIRROR_2000,y
	jsr Lbl_00_8000
	ldy $2d
	pla 
	sta $13
	lda.w AOROM_BANK_PPU_MIRROR_2000,y
	sta.w AOROM_BANK_PPU_MIRROR_2000,y
	rts


/**
* bank LUT (avoids bus conflict on bank select), also with/out ppu mirroring flag
*/
AOROM_BANK_PPU_MIRROR_2000:
	.byte $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f

AOROM_BANK_PPU_MIRROR_2400:
	.byte $10,$11,$12,$13,$14,$15,$16,$17


/**
* trampoline bank 0
*/
Lbl_00_8000:
	jmp ($0013)

/**
* jump table bank 0
*/
Lbl_00_8003:
	jmp Lbl_00_e7b2

Lbl_00_8006:
	jmp Lbl_00_8326

etc.


/**
* trampoline bank 1
*/
Lbl_01_8000:
	jmp ($0013)

/**
* jump table bank 1
*/
Lbl_01_8003:
	jmp Lbl_01_80a2

Lbl_01_8006:
	jmp Lbl_01_8719

etc.


/**
* sample routine, bank 1
*/
Lbl_01_8719:
	lda #$17
	sta $b3
	lda #$d0
	sta $b4
	lda #$86
	sta $95
	lda $b5
	ror a 
	ror a 
	ror a 
	and #$c0
	tay 
	ldx #$60

Lbl_01_872f:
	lda.w Lbl_01_8619,y
	sta $0100,x
	iny 
	inx 
	cpx #$a0
	bne Lbl_01_872f
	rts 


relevant routines modified to use long jumps instead while preserving interface (minus ppu mirror flags, which would probably best be handled in the graphics subsystem instead):

Code: Select all

/**
* jump to subroutine, long (no ppu mirror flag handling here)
* 
* @param x	(target routine number + 1) * 3
* @param y	target bank
*/
Lbl_00_ffcd:

	;save previous jump target for whatever reason
	php
	pei ($13)

	;prepare pointer to target bank
	rep #$30
	lda #Lbl_00_8000
	sta $13
	sep #$20
	tya
	sta $15

	;execute jump
	jsl longJump

	;restore previous jump target
	rep #$30
	pla 
	sta $13
	plp
	rts

longJump:
  jml [$13]


/**
* trampoline bank 0
*/
Lbl_00_8000:
	dex
	dex
	jsr (Lbl_00_8003,x)
	rtl

/**
* jump table bank 0
*/

Lbl_00_8003:
	jmp Lbl_00_e7b2

Lbl_00_8006:
	jmp Lbl_00_8326

etc.


/**
* trampoline bank 1
*/
Lbl_01_8000:
	dex
	dex
	jsr (Lbl_01_8003,x)
	rtl

/**
* jump table bank 1
*/
Lbl_01_8003:
	jmp Lbl_01_80a2

Lbl_01_8006:
	jmp Lbl_01_8719

etc.
To be honest, I don't think this example is terribly useful, because these modifications highly depend on the games actual implementation, but maybe it will give you some ideas.
As already hinted at earlier, I'm not actually using the above code snippet, because it feels hackish and not very maintainable to me.

Posted: Fri Sep 02, 2011 10:59 am
by Hamtaro126
Thank you a lot, d4s. This will help me a lot!

And I will give credit when used, if nessicary.

Posted: Sun Sep 04, 2011 11:28 am
by d4s
Hamtaro126 wrote: And I will give credit when used, if nessicary.
Don't mention it, it's nothing.
But please report back when you're making progress, I'm curious!