Skip to content

Commit adb2872

Browse files
committed
init
0 parents  commit adb2872

21 files changed

+1176
-0
lines changed

.cargo/config.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[build]
2+
target = "mos-nes-cnrom-none"
3+
4+
[target.mos-nes-cnrom-none]
5+
rustflags = [
6+
"-C", "link-arg=-Tsrc/link.ld",
7+
"-C", "link-arg=-Wl,--verbose",
8+
# export RUSTC_LOG=rustc_codegen_ssa::back::link=info
9+
]
10+
11+
[unstable]
12+
build-std = ["core", "alloc"]

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
/Cargo.lock

Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "brickgame"
3+
version = "0.2.0"
4+
edition = "2021"
5+
6+
[profile.release]
7+
opt-level = 3
8+
lto = true
9+
debug = false
10+
debug-assertions = false
11+
panic = "abort"
12+
codegen-units = 1
13+
14+
[build-dependencies]
15+
cc = { version = "1.0"}
16+
17+
[dependencies]
18+
numtoa = "0.2.4"
19+
20+
[features]
21+
skip-legal = []
22+
stress = []
23+
debug = []
24+
tas-compat = []

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## goals
2+
3+
* leaderboard compat [x]
4+
* sfx [x]
5+
* doesn't crash [x]
6+
* ctm compat [ ]
7+
* gym compat [ ]
8+
9+
## building
10+
11+
```bash
12+
node src/chr/convert.js src/chr
13+
docker pull mrkits/rust-mos
14+
docker run -it --name rustmos --entrypoint bash -v ${HOME}/tetris/rust:/hostfiles mrkits/rust-mos
15+
docker container exec -it rustmos /bin/bash
16+
cargo build --release
17+
```
18+
19+
## attribution
20+
21+
* original engine remake & implementation help https://github.com/negative-seven/meta_nestris
22+
* linker help https://github.com/jgouly
23+
* original disassembly https://github.com/ejona86/taus
24+
* public domain font https://opengameart.org/content/intrepid-monochrome-8-bit-font
25+
* toolchain https://llvm-mos.org/wiki/Rust

build.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
cc::Build::new()
3+
.compiler("clang")
4+
.target("mos-nes")
5+
.file("src/nmi.c")
6+
.compile("nmi");
7+
}

scripts/call_log.lua

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
if tastudio then -- bizhawk
2+
shift_right = bit.rshift
3+
bitwise_and = bit.band
4+
bitwise_xor = bit.bxor
5+
read_byte = memory.read_u8
6+
read_word = memory.read_u16_le
7+
get_cycles = emu.totalexecutedcycles
8+
function get_program_counter()
9+
return emu.getregister('PC')
10+
end
11+
function get_stack_pointer()
12+
return emu.getregister('S')
13+
end
14+
function register_callback_execute(function_)
15+
event.onmemoryexecuteany(function_)
16+
end
17+
function script_suffix()
18+
event.onexit(function() io.close(log_file) end)
19+
while true do
20+
emu.frameadvance()
21+
end
22+
end
23+
else -- mesen (assumed)
24+
function read_byte(address)
25+
return emu.read(address, emu.memType.cpuDebug)
26+
end
27+
function read_word(address)
28+
return emu.readWord(address, emu.memType.cpuDebug)
29+
end
30+
function get_cycles()
31+
return emu.getState().cpu.cycleCount
32+
end
33+
function get_program_counter()
34+
return emu.getState().cpu.pc
35+
end
36+
function get_stack_pointer()
37+
return emu.getState().cpu.sp
38+
end
39+
print = emu.log
40+
function register_callback_execute(function_)
41+
emu.addMemoryCallback(function_, emu.memCallbackType.cpuExec, 0x0, 0xffff)
42+
end
43+
function script_suffix() end
44+
end
45+
46+
log_file = io.open('call_log.txt', 'w')
47+
48+
returns = {}
49+
last_cycles = 0
50+
51+
register_callback_execute(function()
52+
pc = get_program_counter()
53+
opcode = read_byte(pc)
54+
new_cycles = get_cycles() - last_cycles
55+
56+
if opcode == 0x20 then -- JSR
57+
operand = read_word(pc + 1)
58+
59+
log_file:write(string.format('jsr to %04x (pc: %04x, cycles: +%d)\n', operand, pc, new_cycles))
60+
returns[pc + 2] = operand
61+
last_cycles = get_cycles()
62+
elseif opcode == 0x60 then -- RTS
63+
return_address = read_word(0x100 + get_stack_pointer() + 1)
64+
65+
return_string = returns[return_address] and
66+
string.format('%04x', returns[return_address]) or
67+
'unknown'
68+
69+
log_file:write(string.format('rts from %s (pc: %04x, cycles: +%d)\n', return_string, pc, new_cycles))
70+
returns[return_address] = nil
71+
last_cycles = get_cycles()
72+
end
73+
end)
74+
75+
script_suffix()

scripts/cycles.lua

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
waitForVBlankTrigger = false
2+
lastCycles = nil
3+
highestShort = 0
4+
highCountShort = 0
5+
highestLong = 0
6+
highCountLong = 0
7+
8+
function startFrame(address, value)
9+
state = emu.getState()
10+
waitForVBlankTrigger = false
11+
lastCycles = state.cpu.cycleCount
12+
highCountShort = highCountShort + 1
13+
highCountLong = highCountLong + 1
14+
if highCountShort > 30 then
15+
highCountShort = 0
16+
highestShort = 0
17+
end
18+
if highCountLong > 60*2 then
19+
highCountLong = 0
20+
highestLong = 0
21+
end
22+
end
23+
24+
function cyclePCT(cycles)
25+
return string.format(" (%d%%)", math.floor((cycles / 29780.5)*100))
26+
end
27+
28+
function vblankCheck(address, value)
29+
if waitForVBlankTrigger == false then
30+
waitForVBlankTrigger = true
31+
state = emu.getState()
32+
diff = state.cpu.cycleCount - lastCycles
33+
if diff > highestShort then
34+
highestShort = diff
35+
end
36+
if diff > highestLong then
37+
highestLong = diff
38+
end
39+
emu.drawRectangle(8, 8, 150, 36, 0x000000, true, 1)
40+
emu.drawString(12, 9, "used cycles - " .. diff .. cyclePCT(diff), 0xFFFFFF, 0xFF000000, 1)
41+
emu.drawString(12, 21, "highest/sec/2 - " .. highestShort .. cyclePCT(highestShort), 0xFFFFFF, 0xFF000000, 1)
42+
emu.drawString(12, 33, "highest/2sec - " .. highestLong .. cyclePCT(highestLong), 0xFFFFFF, 0xFF000000, 1)
43+
end
44+
end
45+
emu.addMemoryCallback(vblankCheck, emu.memCallbackType.cpuRead, 0x80)
46+
emu.addEventCallback(startFrame, emu.eventType.startFrame)

scripts/disasm.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
tail -c +17 ./target/mos-nes-cnrom-none/release/rust-nes | head -c 32768 > target/PRG.bin
4+
5+
cp scripts/symbols.info target/symbols.info
6+
node scripts/get-symbols.js >> target/symbols.info
7+
8+
da65 -i target/symbols.info --comments 3 target/PRG.bin > target/PRG.s

scripts/get-symbols.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const symbols = require('child_process').execSync('nm -anC ./target/mos-nes-cnrom-none/release/deps/*.elf').toString();
2+
const lines = [];
3+
const usedAddr = {};
4+
symbols.toString().trim().split('\n').forEach(line => {
5+
const [addr, type, name] = line.split(' ');
6+
if (true || 'at'.includes(type.toLowerCase())) {
7+
if (parseInt(addr, 16) < 0x10000 && !usedAddr[addr]) {
8+
usedAddr[addr] = true;
9+
lines.push(`LABEL { ADDR $${addr}; NAME ${JSON.stringify(name)}; };`);
10+
}
11+
}
12+
});
13+
console.log(lines.join('\n'));

scripts/symbols.info

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# https://www.cc65.org/doc/da65-4.html
2+
GLOBAL {
3+
STARTADDR $8000;
4+
};
5+
6+
SEGMENT { START $FFFA; END $FFFF; NAME "VECTORS"; };
7+
LABEL { ADDR $2000; NAME "PPUCTRL"; };
8+
LABEL { ADDR $2001; NAME "PPUMASK"; };
9+
LABEL { ADDR $2002; NAME "PPUSTATUS"; };
10+
LABEL { ADDR $2003; NAME "OAMADDR"; };
11+
LABEL { ADDR $2004; NAME "OAMDATA"; };
12+
LABEL { ADDR $2005; NAME "PPUSCROLL"; };
13+
LABEL { ADDR $2006; NAME "PPUADDR"; };
14+
LABEL { ADDR $2007; NAME "PPUDATA"; };
15+
16+
LABEL { ADDR $4000; NAME "SQ1_VOL"; };
17+
LABEL { ADDR $4001; NAME "SQ1_SWEEP"; };
18+
LABEL { ADDR $4002; NAME "SQ1_LO"; };
19+
LABEL { ADDR $4003; NAME "SQ1_HI"; };
20+
LABEL { ADDR $4004; NAME "SQ2_VOL"; };
21+
LABEL { ADDR $4005; NAME "SQ2_SWEEP"; };
22+
LABEL { ADDR $4006; NAME "SQ2_LO"; };
23+
LABEL { ADDR $4007; NAME "SQ2_HI"; };
24+
LABEL { ADDR $4008; NAME "TRI_LINEAR"; };
25+
# $4009 is unused
26+
LABEL { ADDR $400A; NAME "TRI_LO"; };
27+
LABEL { ADDR $400B; NAME "TRI_HI"; };
28+
LABEL { ADDR $400C; NAME "NOISE_VOL"; };
29+
# $400D is unused
30+
LABEL { ADDR $400E; NAME "NOISE_LO"; };
31+
LABEL { ADDR $400F; NAME "NOISE_HI"; };
32+
LABEL { ADDR $4010; NAME "DMC_FREQ"; };
33+
LABEL { ADDR $4011; NAME "DMC_RAW"; };
34+
LABEL { ADDR $4012; NAME "DMC_START"; COMMENT "start << 6 + $C000"; };
35+
LABEL { ADDR $4013; NAME "DMC_LEN"; COMMENT "len << 4 + 1 "; };
36+
LABEL { ADDR $4014; NAME "OAMDMA"; };
37+
LABEL { ADDR $4015; NAME "SND_CHN"; };
38+
LABEL { ADDR $4016; NAME "JOY1"; };
39+
LABEL { ADDR $4017; NAME "JOY2_APUFC"; COMMENT "read: bits 0-4 joy data lines (bit 0 being normal controller), bits 6-7 are FC inhibit and mode"; };
40+
# $4018-$401F normally disabled
41+
42+
# Code and tables
43+
# BYTETABLE
44+
LABEL { ADDR $FF00; NAME "reset"; COMMENT "incremented to reset MMC1 reg"; };
45+
RANGE { START $FFFA; END $FFFF; TYPE ADDRTABLE; }; # interrupts

0 commit comments

Comments
 (0)