Skip to content
This repository was archived by the owner on May 19, 2025. It is now read-only.

Commit e26ec17

Browse files
author
moatom
committed
Find a cpu's bug.
1 parent d5e8d80 commit e26ec17

File tree

11 files changed

+242
-58
lines changed

11 files changed

+242
-58
lines changed

Makefile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
SMLSHARP = smlsharp
22
all: main
3-
main: cpu.o mapper.o main.o cpu.smi mapper.smi main.smi
3+
main: common.o ppu.o cpu.o mapper.o main.o common.smi ppu.smi cpu.smi \
4+
mapper.smi main.smi
45
$(SMLSHARP) $(LDFLAGS) -o $@ main.smi $(LIBS)
5-
cpu.o: cpu.sml cpu.smi
6+
common.o: common.sml common.smi
7+
$(SMLSHARP) $(SMLFLAGS) -o $@ -c common.sml
8+
ppu.o: ppu.sml common.smi ppu.smi
9+
$(SMLSHARP) $(SMLFLAGS) -o $@ -c ppu.sml
10+
cpu.o: cpu.sml common.smi ppu.smi cpu.smi
611
$(SMLSHARP) $(SMLFLAGS) -o $@ -c cpu.sml
7-
mapper.o: mapper.sml cpu.smi mapper.smi
12+
mapper.o: mapper.sml common.smi ppu.smi cpu.smi mapper.smi
813
$(SMLSHARP) $(SMLFLAGS) -o $@ -c mapper.sml
9-
main.o: main.sml cpu.smi mapper.smi main.smi
14+
main.o: main.sml common.smi ppu.smi cpu.smi mapper.smi main.smi
1015
$(SMLSHARP) $(SMLFLAGS) -o $@ -c main.sml

common.smi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
_require "basis.smi"
2+
3+
structure Common =
4+
struct
5+
val rd : word8 array * word16 -> word8
6+
val wr : word8 array * word16 * word8 -> unit
7+
exception MemFault
8+
val pow : int * int -> int
9+
end

common.sml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
structure Common =
2+
struct
3+
fun rd (device, addr): word8 = Array.sub (device, Word16.toInt addr)
4+
fun wr (device, addr, value): unit = Array.update (device, Word16.toInt addr, value)
5+
exception MemFault
6+
fun pow (a, 0) = 1
7+
| pow (a, b) = a * pow (a, b-1)
8+
end

cpu.smi

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
_require "basis.smi"
2+
_require "ppu.smi"
23

34
structure CPU =
45
struct
5-
val wram : word8 array
6+
val wRam : word8 array
67
val ppuRegisters : word8 array
7-
val cartridge : word8 array
8+
val prgRom : word8 array
89

910
val w8ToW16 : word8 -> word16
1011
(* val w16ToW8 : word16 -> word8 *)
@@ -120,6 +121,6 @@ struct
120121
val fetchAndDecode : word16 -> instruction * word16 * int
121122

122123
val alignDigit : word8 -> string
123-
val prtRegs : registers -> unit
124-
val cpu : registers -> registers * int
124+
val prtRegs : registers * int -> unit
125+
val cpu : registers * int -> registers * int
125126
end

cpu.sml

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
structure CPU =
22
struct
3-
val wram : word8 array = Array.array (4 * Word.toInt 0wx800, 0wx0: word8)
3+
val wRam : word8 array = Array.array (4 * Word.toInt 0wx800, 0wx0: word8)
44
val ppuRegisters : word8 array = Array.array (Word.toInt (0wx8+0wx1FF8), 0wx0: word8)
5-
val cartridge : word8 array = Array.array (Word.toInt 0wxBFE0, 0wx0: word8)
5+
val prgRom : word8 array = Array.array (Word.toInt 0wxBFE0, 0wx0: word8)
66

77
fun w8ToW16 w8 = Word16.fromInt (Word8.toInt w8)
88
fun w16ToW8 w16 = Word8.fromInt (Word16.toInt w16)
@@ -19,23 +19,24 @@ struct
1919
end
2020
exception MemFault
2121
fun read (addr: word16): word8 =
22-
if addr < 0wx2000 then rd (wram, addr)
22+
if addr < 0wx2000 then rd (wRam, addr)
2323
else if addr < 0wx4000 then rd (ppuRegisters, addr-0wx2000)
2424
else if addr < 0wx4020 then raise MemFault
25-
else if addr < 0wxFFFF then rd (cartridge, addr-0wx4020)
25+
else if addr < 0wxFFFF then rd (prgRom, addr-0wx4020)
2626
else raise MemFault
2727
fun read16 (addr: word16): word16 =
28-
if addr < 0wx2000 then rd16 (wram, addr)
28+
if addr < 0wx2000 then rd16 (wRam, addr)
2929
else if addr < 0wx4020 then raise MemFault
30-
else if addr < 0wxFFFF then rd16 (cartridge, addr-0wx4020)
30+
else if addr < 0wxFFFF then rd16 (prgRom, addr-0wx4020)
3131
else raise MemFault
3232
fun write (addr, value) : unit =
33-
if addr < 0wx2000 then wr (wram, addr, value)
33+
if addr < 0wx2000 then wr (wRam, addr, value)
34+
else if addr < 0wx2008 then PPU.ioWrite (addr, value)
3435
else if addr < 0wx4020 then raise MemFault
3536
else if addr < 0wxFFFF then raise MemFault
3637
else raise MemFault
3738
fun write16 (addr, value) : unit =
38-
if addr < 0wx2000 then wr16 (wram, addr, value)
39+
if addr < 0wx2000 then wr16 (wRam, addr, value)
3940
else if addr < 0wx4020 then raise MemFault
4041
else if addr < 0wxFFFF then raise MemFault
4142
else raise MemFault
@@ -63,7 +64,7 @@ struct
6364

6465

6566
fun samePageRead16 addr =
66-
Word16.orb (w8ToW16 (rd (wram, addr)), Word16.<< (w8ToW16 (rd (wram, Word16.orb (Word16.andb (addr, 0wxff00), (addr+0wx1) mod 0wx100))), 0wx8))
67+
Word16.orb (w8ToW16 (rd (wRam, addr)), Word16.<< (w8ToW16 (rd (wRam, Word16.orb (Word16.andb (addr, 0wxff00), (addr+0wx1) mod 0wx100))), 0wx8))
6768

6869
fun isCrossed (a, b) = Word16.andb (a, 0wxff00) <> Word16.andb (b, 0wxff00)
6970

@@ -456,21 +457,22 @@ struct
456457
end
457458

458459
fun alignDigit w = (if 0wx0 <= w andalso w <= 0wxF then "0" else "") ^ Word8.toString w
459-
fun prtRegs regs =
460+
fun prtRegs (regs, cycle) =
460461
print ( Word16.toString (#PC regs)
461462
^ ( ":" ^ Word8.toString (read (#PC regs)) ^ " " ^ Word8.toString (read (0w1 + #PC regs)) ^ " " ^ Word8.toString (read (0w2 + #PC regs)))
462463
^ " A:" ^ alignDigit (#A regs)
463464
^ " X:" ^ alignDigit (#X regs)
464465
^ " Y:" ^ alignDigit (#Y regs)
465466
^ " P:" ^ Word8.toString (p2Word (#P regs))
466467
^ " SP:" ^ Word8.toString (#S regs)
468+
^ " CYC:" ^ Int.toString cycle
467469
^ "\n")
468470

469-
fun cpu regs =
471+
fun cpu (regs, cycle) =
470472
let
471473
val (insn, nextPc, baseCycle) = fetchAndDecode (#PC regs)
472474
val (newRegs, additionalCycle) = exec (regs # {PC = nextPc}, insn)
473475
in
474-
(prtRegs regs; (newRegs, baseCycle + additionalCycle))
476+
(prtRegs (regs, cycle); (newRegs, cycle + baseCycle + additionalCycle))
475477
end
476478
end

main.smi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
_require "basis.smi"
22
_require "./cpu.smi"
3-
(* _require "./ppu.smi" *)
3+
_require "./ppu.smi"
44
_require "./mapper.smi"

main.sml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
val StatusRegister = {N=false, V=false, B5=true, B4=false, D=false, I=true, Z=false, C=false}
2-
3-
fun frame (regs, cycle) =
2+
type cpuData = {regs : CPU.registers, cycle : int}
3+
val CYCLES_PER_FRAME = 263 * 341 div 3 - 1
4+
5+
fun printScreen pic = ()
6+
fun frame cData =
47
let
5-
val (newRegs, newCycle) = CPU.cpu regs
6-
(* val updatedCycle = PPU.ppu ((cycle+newCycle)*3) *)
8+
val (newCpuRegs, newCpuCycle) = CPU.cpu (#regs cData, #cycle cData)
79
in
8-
()
9-
(* frame (newRegs, updatedCycle) *)
10+
if newCpuCycle > CYCLES_PER_FRAME
11+
then (printScreen (PPU.ppu ());
12+
frame (cData # {regs = newCpuRegs, cycle = 0}))
13+
else frame (cData # {regs = newCpuRegs, cycle = newCpuCycle})
1014
end
1115

12-
1316
fun run _ =
1417
(
1518
Mapper.init ();
16-
frame ({A=0w0, X=0w0, Y=0w0, PC= CPU.read16 0wxfffc, S=0wxFD, P=StatusRegister}, 0)
19+
frame {regs = {A=0w0, X=0w0, Y=0w0, PC= CPU.read16 0wxfffc, S=0wxFD, P=StatusRegister}, cycle = 27280}
1720
)
1821

1922
val _ = run ()

mapper.smi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
_require "basis.smi"
22
_require "./cpu.smi"
3+
_require "./ppu.smi"
34

45
structure Mapper =
56
struct

mapper.sml

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,60 @@ structure Mapper =
22
struct
33
fun init _ =
44
let
5-
val file = BinIO.openIn "../../sample1/sample1.nes"
6-
val prgrom : word8 vector = BinIO.inputAll file
5+
val file = BinIO.openIn "./sample1/sample1.nes"
6+
val cartridge : word8 vector = BinIO.inputAll file
77
val _ = BinIO.closeIn file
8-
fun mapper0 n =
8+
9+
val promUnits = Vector.sub (cartridge, 4)
10+
val cromStart = 16 + 16384 * Word8.toInt promUnits
11+
fun processCrom 8192 = ()
12+
| processCrom n =
13+
(
14+
Array.update (PPU.chrRom, n, Vector.sub (cartridge, n + cromStart));
15+
processCrom (n+1)
16+
)
17+
fun mapper0 _ =
918
let
10-
val units = Vector.sub (prgrom, 4)
11-
fun nrom128 16384 = ()
12-
| nrom128 n =
19+
fun nrom128 n =
1320
let
14-
val subed = Vector.sub (prgrom, n+16)
15-
val target = n + Word.toInt (0wx8000-0wx4020)
21+
fun processProm 16384 = ()
22+
| processProm n =
23+
let
24+
val subed = Vector.sub (cartridge, n+16)
25+
val target = n + Word.toInt (0wx8000-0wx4020)
26+
in
27+
(
28+
Array.update (CPU.prgRom, target, subed);
29+
Array.update (CPU.prgRom, target + 16384, subed);
30+
processProm (n+1)
31+
)
32+
end
1633
in
17-
(Array.update (CPU.cartridge, target, subed);
18-
Array.update (CPU.cartridge, target + 16384, subed);
19-
nrom128 (n+1))
34+
(processProm n; processCrom n)
2035
end
21-
fun nrom256 32768 = ()
22-
| nrom256 n =
36+
fun nrom256 n =
2337
let
24-
val subed = Vector.sub (prgrom, n+16)
25-
val target = n + Word.toInt (0wx8000-0wx4020)
38+
fun processProm 32768 = ()
39+
| processProm n =
40+
let
41+
val subed = Vector.sub (cartridge, n+16)
42+
val target = n + Word.toInt (0wx8000-0wx4020)
43+
in
44+
(
45+
Array.update (CPU.prgRom, target, subed);
46+
processProm (n+1)
47+
)
48+
end
2649
in
27-
(Array.update (CPU.cartridge, target, subed);
28-
nrom256 (n+1))
50+
(processProm n; processCrom n)
2951
end
3052
in
31-
case units of
32-
0w1 => nrom128 n
33-
| 0w2 => nrom256 n
53+
case promUnits of
54+
0w1 => nrom128 0
55+
| 0w2 => nrom256 0
3456
| _ => ()
3557
end
3658
in
37-
mapper0 0
59+
mapper0 ()
3860
end
3961
end

ppu.smi

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
_require "basis.smi"
2+
_require "common.smi"
23

34
structure PPU =
45
struct
5-
val ppu : cycle -> unit
6+
val chrRom : word8 array
7+
val vRam : word8 array
8+
9+
val read : word16 -> word8
10+
val write : word16 * word8 -> unit
11+
val ioWrite : word16 * word8 -> unit
12+
13+
val ppu : unit -> word32 array
614
end

0 commit comments

Comments
 (0)