Skip to content

MMC1 512K PRG support #396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
28ab2c9
MMC1 512K PRG support
sebastienvezina Apr 28, 2025
17b9b48
Fixed double __ in register names
sebastienvezina Apr 28, 2025
88e2cb5
vscode plugin ignore - not needed
sebastienvezina Apr 28, 2025
a00393e
skip set CHR bits if switch to bank < 16
sebastienvezina Apr 28, 2025
9993ac2
fix switching to a high bank was exiting early in the middle of the b…
sebastienvezina Apr 28, 2025
d11ec30
replaced cmp/bne w and/beq
sebastienvezina Apr 28, 2025
085fec1
update actual registers
sebastienvezina Apr 28, 2025
659a4a0
nes-mmc1 prg 512 unit tests
sebastienvezina Apr 28, 2025
2610b30
hex to lowercase + removed references to prg 15
sebastienvezina Apr 28, 2025
cc334b9
jrowboy's set_prg_bank
sebastienvezina Apr 29, 2025
af1dc55
review https://github.com/llvm-mos/llvm-mos-sdk/pull/396#discussion_r…
sebastienvezina Apr 29, 2025
1661294
fix https://github.com/llvm-mos/llvm-mos-sdk/pull/396#discussion_r206…
sebastienvezina Apr 29, 2025
a93c409
fix https://github.com/llvm-mos/llvm-mos-sdk/pull/396#discussion_r206…
sebastienvezina Apr 29, 2025
48992f0
latest version of set_prg_bank but still use prg_rom_is_512 which sho…
sebastienvezina Apr 29, 2025
a1a1df2
attempt at fixing the fixed bank output format
sebastienvezina Apr 29, 2025
ed2856d
added __ prefix to prg_rom_is_512
sebastienvezina Apr 29, 2025
181ecda
try to preserve the PRG RAM bit
sebastienvezina Apr 29, 2025
500564c
Added prg-rom-512 test to list
sebastienvezina Apr 30, 2025
b62a60f
banked_call fiddling because set_prg_bank clobbers rc2 and/or rc3
sebastienvezina May 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ build/**
build*
*~
*.rej
.qodo
2 changes: 1 addition & 1 deletion mos-platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ add_subdirectory(pce)
add_subdirectory(pce-cd)
add_subdirectory(rp6502)
add_subdirectory(supervision)
add_subdirectory(vic20)
# add_subdirectory(vic20)
52 changes: 37 additions & 15 deletions mos-platform/nes-mmc1/mapper.s
Original file line number Diff line number Diff line change
Expand Up @@ -99,23 +99,45 @@ get_prg_bank:
.weak set_prg_bank
__set_prg_bank:
set_prg_bank:
tay
bit .Luse_suxrom_bankswitching
bpl .Lcontinue_bank_switch
; save the new bank byte on the stack for safe keeping
pha
; check which bits changed
eor _PRG_BANK
; if the outer bank bit changed then we need to set a new outerbank
and #%00010000
beq .Lset_inner_bank
.Lset_new_outer_bank:
; Flip the outer bank bit for _CHR_BANK0 and _CHR_BANK1
lda _CHR_BANK0
eor #%00010000
jsr set_chr_bank_0_retry
lda _CHR_BANK1
eor #%00010000
jsr set_chr_bank_1_retry
.Lset_inner_bank:
; restore the bank byte and put it in y so we can reload it on retry
pla
.Lcontinue_bank_switch:
tay
; original code below
.Lset:
inc __reset_mmc1_byte
ldx #1
stx _IN_PROGRESS
mmc1_register_write MMC1_PRG
ldx _IN_PROGRESS
beq .Lretry
dex
stx _IN_PROGRESS
sty _PRG_BANK
rts
inc __reset_mmc1_byte
ldx #1
stx _IN_PROGRESS
mmc1_register_write MMC1_PRG
ldx _IN_PROGRESS
beq .Lretry
dex
stx _IN_PROGRESS
sty _PRG_BANK
rts
.Lretry:
tya
jmp .Lset


tya
jmp .Lset
.Luse_suxrom_bankswitching:
.byte ((<prg_rom_is_512) << 7)

.section .text.banked_call,"ax",@progbits
.weak banked_call
Expand Down
82 changes: 81 additions & 1 deletion mos-platform/nes-mmc1/prg-rom-banked.ld
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ __prg_rom_11_lma = 0x0b8000;
__prg_rom_12_lma = 0x0c8000;
__prg_rom_13_lma = 0x0d8000;
__prg_rom_14_lma = 0x0e8000;
__prg_rom_16_lma = 0x108000;
__prg_rom_17_lma = 0x118000;
__prg_rom_18_lma = 0x128000;
__prg_rom_19_lma = 0x138000;
__prg_rom_20_lma = 0x148000;
__prg_rom_21_lma = 0x158000;
__prg_rom_22_lma = 0x168000;
__prg_rom_23_lma = 0x178000;
__prg_rom_24_lma = 0x188000;
__prg_rom_25_lma = 0x198000;
__prg_rom_26_lma = 0x1a8000;
__prg_rom_27_lma = 0x1b8000;
__prg_rom_28_lma = 0x1c8000;
__prg_rom_29_lma = 0x1d8000;
__prg_rom_30_lma = 0x1e8000;
__prg_rom_fixed_lma = 0xc000;

__prg_rom_0_offset = 0x00000;
Expand All @@ -32,6 +47,21 @@ __prg_rom_11_offset = 0x2c000;
__prg_rom_12_offset = 0x30000;
__prg_rom_13_offset = 0x34000;
__prg_rom_14_offset = 0x38000;
__prg_rom_16_offset = 0x40000;
__prg_rom_17_offset = 0x44000;
__prg_rom_18_offset = 0x48000;
__prg_rom_19_offset = 0x4c000;
__prg_rom_20_offset = 0x50000;
__prg_rom_21_offset = 0x54000;
__prg_rom_22_offset = 0x58000;
__prg_rom_23_offset = 0x5c000;
__prg_rom_24_offset = 0x60000;
__prg_rom_25_offset = 0x64000;
__prg_rom_26_offset = 0x68000;
__prg_rom_27_offset = 0x6c000;
__prg_rom_28_offset = 0x70000;
__prg_rom_29_offset = 0x74000;
__prg_rom_30_offset = 0x78000;
__prg_rom_fixed_offset = __prg_rom_size * 1024 - 0x4000;

MEMORY {
Expand All @@ -51,6 +81,21 @@ MEMORY {
prg_rom_12 : ORIGIN = __prg_rom_12_lma, LENGTH = __prg_rom_size >= 256 ? 0x4000 - 12 : 0
prg_rom_13 : ORIGIN = __prg_rom_13_lma, LENGTH = __prg_rom_size >= 256 ? 0x4000 - 12 : 0
prg_rom_14 : ORIGIN = __prg_rom_14_lma, LENGTH = __prg_rom_size >= 256 ? 0x4000 - 12 : 0
prg_rom_16 : ORIGIN = __prg_rom_16_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_17 : ORIGIN = __prg_rom_17_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_18 : ORIGIN = __prg_rom_18_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_19 : ORIGIN = __prg_rom_19_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_20 : ORIGIN = __prg_rom_20_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_21 : ORIGIN = __prg_rom_21_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_22 : ORIGIN = __prg_rom_22_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_23 : ORIGIN = __prg_rom_23_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_24 : ORIGIN = __prg_rom_24_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_25 : ORIGIN = __prg_rom_25_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_26 : ORIGIN = __prg_rom_26_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_27 : ORIGIN = __prg_rom_27_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_28 : ORIGIN = __prg_rom_28_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_29 : ORIGIN = __prg_rom_29_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_30 : ORIGIN = __prg_rom_30_lma, LENGTH = __prg_rom_size >= 512 ? 0x4000 - 12 : 0
prg_rom_fixed : ORIGIN = __prg_rom_fixed_lma, LENGTH = 0x4000 - 12

/* Reset stub. Arbitrarily put its VMA in the first bank. */
Expand Down Expand Up @@ -78,6 +123,21 @@ SECTIONS {
.prg_rom_12 : { *(.prg_rom_12 .prg_rom_12.*) } >prg_rom_12
.prg_rom_13 : { *(.prg_rom_13 .prg_rom_13.*) } >prg_rom_13
.prg_rom_14 : { *(.prg_rom_14 .prg_rom_14.*) } >prg_rom_14
.prg_rom_16 : { *(.prg_rom_16 .prg_rom_16.*) } >prg_rom_16
.prg_rom_17 : { *(.prg_rom_17 .prg_rom_17.*) } >prg_rom_17
.prg_rom_18 : { *(.prg_rom_18 .prg_rom_18.*) } >prg_rom_18
.prg_rom_19 : { *(.prg_rom_19 .prg_rom_19.*) } >prg_rom_19
.prg_rom_20 : { *(.prg_rom_20 .prg_rom_20.*) } >prg_rom_20
.prg_rom_21 : { *(.prg_rom_21 .prg_rom_21.*) } >prg_rom_21
.prg_rom_22 : { *(.prg_rom_22 .prg_rom_22.*) } >prg_rom_22
.prg_rom_23 : { *(.prg_rom_23 .prg_rom_23.*) } >prg_rom_23
.prg_rom_24 : { *(.prg_rom_24 .prg_rom_24.*) } >prg_rom_24
.prg_rom_25 : { *(.prg_rom_25 .prg_rom_25.*) } >prg_rom_25
.prg_rom_26 : { *(.prg_rom_26 .prg_rom_26.*) } >prg_rom_26
.prg_rom_27 : { *(.prg_rom_27 .prg_rom_27.*) } >prg_rom_27
.prg_rom_28 : { *(.prg_rom_28 .prg_rom_28.*) } >prg_rom_28
.prg_rom_29 : { *(.prg_rom_29 .prg_rom_29.*) } >prg_rom_29
.prg_rom_30 : { *(.prg_rom_30 .prg_rom_30.*) } >prg_rom_30
.prg_rom_fixed : { *(.prg_rom_fixed .prg_rom_fixed.*) } >prg_rom_fixed
}

Expand All @@ -90,6 +150,8 @@ SECTIONS {

PROVIDE(__prg_rom_size = 256);

prg_rom_is_512 = __prg_rom_size >= 512 ? 1 : 0;

OUTPUT_FORMAT {
INCLUDE ines-header.ld
FULL(prg_rom_0) FULL(reset, 0, LENGTH(prg_rom_0) ? LENGTH(reset) : 0)
Expand All @@ -107,6 +169,24 @@ OUTPUT_FORMAT {
FULL(prg_rom_12) FULL(reset, 0, LENGTH(prg_rom_12) ? LENGTH(reset) : 0)
FULL(prg_rom_13) FULL(reset, 0, LENGTH(prg_rom_13) ? LENGTH(reset) : 0)
FULL(prg_rom_14) FULL(reset, 0, LENGTH(prg_rom_14) ? LENGTH(reset) : 0)
FULL(prg_rom_fixed) FULL(reset_fixed)
FULL(prg_rom_fixed) FULL(reset_fixed, 0, __prg_rom_size >= 512 ? 0x4000 - 12 : 0)

FULL(prg_rom_16) FULL(reset, 0, LENGTH(prg_rom_16) ? LENGTH(reset) : 0)
FULL(prg_rom_17) FULL(reset, 0, LENGTH(prg_rom_17) ? LENGTH(reset) : 0)
FULL(prg_rom_18) FULL(reset, 0, LENGTH(prg_rom_18) ? LENGTH(reset) : 0)
FULL(prg_rom_19) FULL(reset, 0, LENGTH(prg_rom_19) ? LENGTH(reset) : 0)
FULL(prg_rom_20) FULL(reset, 0, LENGTH(prg_rom_20) ? LENGTH(reset) : 0)
FULL(prg_rom_21) FULL(reset, 0, LENGTH(prg_rom_21) ? LENGTH(reset) : 0)
FULL(prg_rom_22) FULL(reset, 0, LENGTH(prg_rom_22) ? LENGTH(reset) : 0)
FULL(prg_rom_23) FULL(reset, 0, LENGTH(prg_rom_23) ? LENGTH(reset) : 0)
FULL(prg_rom_24) FULL(reset, 0, LENGTH(prg_rom_24) ? LENGTH(reset) : 0)
FULL(prg_rom_25) FULL(reset, 0, LENGTH(prg_rom_25) ? LENGTH(reset) : 0)
FULL(prg_rom_26) FULL(reset, 0, LENGTH(prg_rom_26) ? LENGTH(reset) : 0)
FULL(prg_rom_27) FULL(reset, 0, LENGTH(prg_rom_27) ? LENGTH(reset) : 0)
FULL(prg_rom_28) FULL(reset, 0, LENGTH(prg_rom_28) ? LENGTH(reset) : 0)
FULL(prg_rom_29) FULL(reset, 0, LENGTH(prg_rom_29) ? LENGTH(reset) : 0)
FULL(prg_rom_30) FULL(reset, 0, LENGTH(prg_rom_30) ? LENGTH(reset) : 0)
FULL(prg_rom_fixed) FULL(reset_fixed, 0, __prg_rom_size >= 512 ? 0x4000 - 12 : 0)

FULL(chr_rom)
}
77 changes: 77 additions & 0 deletions test/nes-mmc1/prg-rom-512.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include <mapper.h>
#include <peekpoke.h>
#include <stdlib.h>

MAPPER_PRG_ROM_KB(512);

volatile const char c[15000] = {1, [14999] = 2};

__attribute__((section(".prg_rom_0.rodata"))) volatile const char d[15000] = {
3, [14999] = 4};

__attribute__((section(".prg_rom_14.rodata"))) volatile const char e[15000] = {
5, [14999] = 6};

__attribute__((section(".prg_rom_29.rodata"))) volatile const char f[15000] = {
7, [14999] = 8};


__attribute__((noinline, section(".prg_rom_0.text"))) char bank_0_fn(void) {
asm volatile("");
return 7;
}

__attribute__((noinline, section(".prg_rom_14.text"))) char bank_14_fn(void) {
asm volatile("");
return 8;
}

__attribute__((noinline, section(".prg_rom_29.text"))) char bank_29_fn(void) {
asm volatile("");
return 10;
}

int main(void) {
if ((unsigned)c < 0xc000)
return EXIT_FAILURE;
if ((unsigned)d >= 0xc000)
return EXIT_FAILURE;
if ((unsigned)e >= 0xc000)
return EXIT_FAILURE;
if ((unsigned)f >= 0xc000)
return EXIT_FAILURE;
if (c[0] != 1 || c[14999] != 2)
return EXIT_FAILURE;

set_prg_bank(0);
if (c[0] != 1 || c[14999] != 2)
return EXIT_FAILURE;
if (d[0] != 3 || d[14999] != 4)
return EXIT_FAILURE;

set_prg_bank(14);
if (c[0] != 1 || c[14999] != 2)
return EXIT_FAILURE;
if (e[0] != 5 || e[14999] != 6)
return EXIT_FAILURE;

set_prg_bank(29);
if (c[0] != 1 || c[14999] != 2)
return EXIT_FAILURE;
if (e[0] != 7 || e[14999] != 8)
return EXIT_FAILURE;

set_prg_bank(0);
if ((unsigned)bank_0_fn >= 0xc000 || bank_0_fn() != 7)
return EXIT_FAILURE;

set_prg_bank(14);
if ((unsigned)bank_14_fn >= 0xc000 || bank_14_fn() != 8)
return EXIT_FAILURE;

set_prg_bank(29);
if ((unsigned)bank_29_fn >= 0xc000 || bank_29_fn() != 10)
return EXIT_FAILURE;

return EXIT_SUCCESS;
}