Skip to content
Browse files

Some MMC2 rework, Punch Out ring is glitched, removed assembly from t…

…est ROMs
  • Loading branch information...
1 parent 29394fc commit f588eedfd4f2f69c1e8f9db835733c0216c605de @scottferg committed Oct 26, 2012
Showing with 114 additions and 9,611 deletions.
  1. +59 −15 apu.go
  2. +1 −0 memory.go
  3. +53 −48 mmc2.go
  4. +1 −6 ppu.go
  5. BIN test_roms/apu_mixer/source/common/ascii.chr
  6. +0 −92 test_roms/apu_mixer/source/common/build_rom.s
  7. +0 −328 test_roms/apu_mixer/source/common/console.s
  8. +0 −118 test_roms/apu_mixer/source/common/crc.s
  9. +0 −190 test_roms/apu_mixer/source/common/delay.s
  10. BIN test_roms/apu_mixer/source/common/devcart.bin
  11. +0 −188 test_roms/apu_mixer/source/common/macros.inc
  12. +0 −56 test_roms/apu_mixer/source/common/neshw.inc
  13. +0 −203 test_roms/apu_mixer/source/common/ppu.s
  14. +0 −247 test_roms/apu_mixer/source/common/print.s
  15. +0 −32 test_roms/apu_mixer/source/common/shell.inc
  16. +0 −180 test_roms/apu_mixer/source/common/shell.s
  17. +0 −211 test_roms/apu_mixer/source/common/shell_misc.s
  18. +0 −105 test_roms/apu_mixer/source/common/testing.s
  19. +0 −61 test_roms/apu_mixer/source/common/text_out.s
  20. +0 −126 test_roms/apu_mixer/source/common/vol_shell.inc
  21. +0 −43 test_roms/apu_mixer/source/dmc.s
  22. +0 −36 test_roms/apu_mixer/source/nes.cfg
  23. +0 −88 test_roms/apu_mixer/source/noise.s
  24. +0 −121 test_roms/apu_mixer/source/readme.txt
  25. +0 −88 test_roms/apu_mixer/source/square.s
  26. +0 −54 test_roms/apu_mixer/source/triangle.s
  27. +0 −60 test_roms/apu_reset/source/4015_cleared.s
  28. +0 −49 test_roms/apu_reset/source/4017_timing.s
  29. +0 −73 test_roms/apu_reset/source/4017_written.s
  30. BIN test_roms/apu_reset/source/common/ascii.chr
  31. +0 −92 test_roms/apu_reset/source/common/build_rom.s
  32. +0 −328 test_roms/apu_reset/source/common/console.s
  33. +0 −118 test_roms/apu_reset/source/common/crc.s
  34. +0 −190 test_roms/apu_reset/source/common/delay.s
  35. BIN test_roms/apu_reset/source/common/devcart.bin
  36. +0 −188 test_roms/apu_reset/source/common/macros.inc
  37. +0 −56 test_roms/apu_reset/source/common/neshw.inc
  38. +0 −203 test_roms/apu_reset/source/common/ppu.s
  39. +0 −247 test_roms/apu_reset/source/common/print.s
  40. +0 −64 test_roms/apu_reset/source/common/run_at_reset.s
  41. +0 −32 test_roms/apu_reset/source/common/shell.inc
  42. +0 −180 test_roms/apu_reset/source/common/shell.s
  43. +0 −211 test_roms/apu_reset/source/common/shell_misc.s
  44. +0 −105 test_roms/apu_reset/source/common/testing.s
  45. +0 −61 test_roms/apu_reset/source/common/text_out.s
  46. +0 −33 test_roms/apu_reset/source/irq_flag_cleared.s
  47. +0 −62 test_roms/apu_reset/source/len_ctrs_enabled.s
  48. +0 −36 test_roms/apu_reset/source/nes.cfg
  49. +0 −121 test_roms/apu_reset/source/readme.txt
  50. +0 −90 test_roms/apu_reset/source/works_immediately.s
  51. +0 −52 test_roms/apu_test/source/1-len_ctr.s
  52. +0 −36 test_roms/apu_test/source/2-len_table.s
  53. +0 −53 test_roms/apu_test/source/3-irq_flag.s
  54. +0 −47 test_roms/apu_test/source/4-jitter.s
  55. +0 −70 test_roms/apu_test/source/5-len_timing.s
  56. +0 −45 test_roms/apu_test/source/6-irq_flag_timing.s
  57. +0 −193 test_roms/apu_test/source/7-dmc_basics.s
  58. +0 −51 test_roms/apu_test/source/8-dmc_rates.s
  59. +0 −32 test_roms/apu_test/source/common/apu_shell.inc
  60. BIN test_roms/apu_test/source/common/ascii.chr
  61. +0 −92 test_roms/apu_test/source/common/build_rom.s
  62. +0 −328 test_roms/apu_test/source/common/console.s
  63. +0 −118 test_roms/apu_test/source/common/crc.s
  64. +0 −190 test_roms/apu_test/source/common/delay.s
  65. BIN test_roms/apu_test/source/common/devcart.bin
  66. +0 −188 test_roms/apu_test/source/common/macros.inc
  67. +0 −56 test_roms/apu_test/source/common/neshw.inc
  68. +0 −203 test_roms/apu_test/source/common/ppu.s
  69. +0 −247 test_roms/apu_test/source/common/print.s
  70. +0 −32 test_roms/apu_test/source/common/shell.inc
  71. +0 −180 test_roms/apu_test/source/common/shell.s
  72. +0 −211 test_roms/apu_test/source/common/shell_misc.s
  73. +0 −28 test_roms/apu_test/source/common/sync_apu.s
  74. +0 −61 test_roms/apu_test/source/common/sync_dmc.s
  75. +0 −34 test_roms/apu_test/source/common/test_main_chans.s
  76. +0 −105 test_roms/apu_test/source/common/testing.s
  77. +0 −61 test_roms/apu_test/source/common/text_out.s
  78. +0 −36 test_roms/apu_test/source/nes.cfg
  79. +0 −121 test_roms/apu_test/source/readme.txt
  80. +0 −126 test_roms/apu_volume_tests/src/hello.s
  81. +0 −81 test_roms/apu_volume_tests/src/pads.s
  82. +0 −285 test_roms/apu_volume_tests/src/sound.s
  83. +0 −80 test_roms/blargg_cpu/source/01-implied.s
  84. +0 −74 test_roms/blargg_cpu/source/02-immediate.s
  85. +0 −93 test_roms/blargg_cpu/source/03-zero_page.s
  86. +0 −118 test_roms/blargg_cpu/source/04-zp_xy.s
  87. +0 −89 test_roms/blargg_cpu/source/05-absolute.s
  88. +0 −143 test_roms/blargg_cpu/source/06-abs_xy.s
  89. +0 −100 test_roms/blargg_cpu/source/07-ind_x.s
  90. +0 −87 test_roms/blargg_cpu/source/08-ind_y.s
  91. +0 −47 test_roms/blargg_cpu/source/09-branches.s
  92. +0 −117 test_roms/blargg_cpu/source/10-stack.s
  93. +0 −28 test_roms/blargg_cpu/source/11-jmp_jsr.s
  94. +0 −38 test_roms/blargg_cpu/source/12-rts.s
Sorry, we could not display the entire diff because it was too big.
View
74 apu.go
@@ -1,24 +1,27 @@
package main
-import (
- "fmt"
+var (
+ DutyLookup = []int{
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 1, 1, 1, 1, 1,
+ }
)
type Square struct {
Volume Word
SawEnvelopeDisabled bool
LengthCounterDisabled bool
DutyCycle Word
- LowPeriod Word
- HighPeriod Word
+ Period int
LengthCounter Word
}
type Triangle struct {
Value Word
InternalCountersDisabled bool
- LowPeriod Word
- HighPeriod Word
+ Period int
LengthCounter Word
}
@@ -39,14 +42,15 @@ func (a *Apu) Init() {
func (a *Apu) RegRead(addr int) (Word, error) {
switch addr {
case 0x4015:
+ // TODO: When a status read occurrs, emulate the APU up to that point.
+ // http://forums.nesdev.com/viewtopic.php?t=2123
return a.ReadStatus(), nil
}
return 0, nil
}
func (a *Apu) RegWrite(v Word, addr int) {
- fmt.Printf("APU RegWrite: 0x%X\n", addr)
switch addr & 0xFF {
case 0x0:
a.WriteSquare1Control(v)
@@ -91,18 +95,58 @@ func (a *Apu) WriteControlFlags1(v Word) {
a.TriangleEnabled = ((v >> 2) & 0x1) == 0x1
a.NoiseEnabled = ((v >> 3) & 0x1) == 0x1
a.DmcEnabled = ((v >> 4) & 0x1) == 0x1
+
+ if !a.Square1Enabled {
+ a.Square1.LengthCounter = 0
+ }
+
+ if !a.Square2Enabled {
+ a.Square2.LengthCounter = 0
+ }
+
+ if !a.TriangleEnabled {
+ a.Triangle.LengthCounter = 0
+ }
+
+ // TODO:
+ // If the DMC bit is clear, the DMC bytes remaining will be
+ // set to 0 and the DMC will silence when it empties.
+ // If the DMC bit is set, the DMC sample will be restarted
+ // only if its bytes remaining is 0. Writing to this register
+ // clears the DMC interrupt flag.
}
// $4015 (r)
func (a *Apu) ReadStatus() Word {
// if-d nt21 DMC IRQ, frame IRQ, length counter statuses
- return 0
+ var status Word
+
+ if a.Square1.LengthCounter > 0 {
+ status |= 0x1
+ }
+
+ if a.Square2.LengthCounter > 0 {
+ status |= 0x2
+ }
+
+ if a.Triangle.LengthCounter > 0 {
+ status |= 0x8
+ }
+
+ // TODO: Noise -> 0x10
+
+ // Reading this register clears the frame interrupt
+ // flag (but not the DMC interrupt flag).
+ // If an interrupt flag was set at the same moment of
+ // the read, it will read back as 1 but it will not be cleared.
+
+ return status
}
// $4017
func (a *Apu) WriteControlFlags2(v Word) {
// fd-- ---- 5-frame cycle, disable frame interrupt
- fmt.Println("WriteControl2!")
+ // fmt.Println("WriteControl2!")
}
// $4000
@@ -125,12 +169,12 @@ func (a *Apu) WriteSquare1Sweeps(v Word) {
// $4002
func (a *Apu) WriteSquare1Low(v Word) {
- a.Square1.LowPeriod = v
+ a.Square1.Period = (a.Square1.Period & 0x700) | int(v)
}
// $4003
func (a *Apu) WriteSquare1High(v Word) {
- a.Square1.HighPeriod = v & 0xF
+ a.Square1.Period = (a.Square1.Period & 0xFF) | int((v&0xF)<<8)
a.Square1.LengthCounter = v >> 3
}
@@ -154,12 +198,12 @@ func (a *Apu) WriteSquare2Sweeps(v Word) {
// $4006
func (a *Apu) WriteSquare2Low(v Word) {
- a.Square2.LowPeriod = v
+ a.Square2.Period = (a.Square1.Period & 0x700) | int(v)
}
// $4007
func (a *Apu) WriteSquare2High(v Word) {
- a.Square2.HighPeriod = v & 0xF
+ a.Square2.Period = (a.Square1.Period & 0xFF) | int((v&0xF)<<8)
a.Square2.LengthCounter = v >> 3
}
@@ -175,11 +219,11 @@ func (a *Apu) WriteTriangleControl(v Word) {
// $400A
func (a *Apu) WriteTriangleLow(v Word) {
- a.Triangle.LowPeriod = v
+ a.Triangle.Period = (a.Triangle.Period & 0x700) | int(v)
}
// $400B
func (a *Apu) WriteTriangleHigh(v Word) {
- a.Triangle.HighPeriod = v & 0xF
+ a.Triangle.Period = (a.Triangle.Period & 0xFF) | int((v&0xF)<<8)
a.Triangle.LengthCounter = v >> 3
}
View
1 memory.go
@@ -68,6 +68,7 @@ func (m *Memory) Write(address interface{}, val Word) error {
m[a] = val
} else if a == 0x4017 {
pads[1].Write(val)
+ apu.RegWrite(val, a)
m[a] = val
} else if a&0xF000 == 0x4000 {
apu.RegWrite(val, a)
View
101 mmc2.go
@@ -1,7 +1,7 @@
package main
import (
- "fmt"
+ "fmt"
)
const (
@@ -22,12 +22,12 @@ type Mmc2 struct {
Battery bool
Data []byte
- Latch0 int
- Latch1 int
- Latch0High int
- Latch1High int
- Latch0Low int
- Latch1Low int
+ latch_a int
+ latch_b int
+ LatchFE0 int
+ LatchFE1 int
+ LatchFD0 int
+ LatchFD1 int
}
func NewMmc2(r *Rom) *Mmc2 {
@@ -40,12 +40,12 @@ func NewMmc2(r *Rom) *Mmc2 {
Data: r.Data,
}
- m.Latch0 = 0xFE
- m.Latch1 = 0xFE
- m.Latch0Low = 0
- m.Latch1Low = 4
- m.Latch0High = 0
- m.Latch1High = 0
+ m.latch_a = 0xFE
+ m.latch_b = 0xFE
+ m.LatchFD0 = 0
+ m.LatchFE0 = 4
+ m.LatchFD1 = 0
+ m.LatchFE1 = 0
m.LoadRom()
@@ -98,22 +98,22 @@ func (m *Mmc2) LatchTrigger(a int) {
a &= 0x1FF0
switch {
- case a == 0xFD0 && m.Latch0 != 0xFD:
- fmt.Printf("Latch A: 0x%X\n", a)
- m.Latch0 = 0xFD
- WriteVramBank(m.VromBanks, m.Latch0Low, 0x0000, Size4k)
- case a == 0xFE0 && m.Latch0 != 0xFE:
- fmt.Printf("Latch A: 0x%X\n", a)
- m.Latch0 = 0xFE
- WriteVramBank(m.VromBanks, m.Latch1Low, 0x0000, Size4k)
- case a == 0x1F00 && m.Latch1 != 0xFD:
- fmt.Printf("Latch A: 0x%X\n", a)
- m.Latch1 = 0xFD
- WriteVramBank(m.VromBanks, m.Latch0High, 0x1000, Size4k)
- case a == 0x1FE0 && m.Latch1 != 0xFE:
- fmt.Printf("Latch A: 0x%X\n", a)
- m.Latch1 = 0xFE
- WriteVramBank(m.VromBanks, m.Latch1High, 0x1000, Size4k)
+ case a == 0x0FD0 && m.latch_a != 0xFD:
+ fmt.Println("Loading FD0")
+ m.latch_a = 0xFD
+ WriteVramBank(m.VromBanks, m.LatchFD0, 0x0000, Size4k)
+ case a == 0x0FE0 && m.latch_a != 0xFE:
+ fmt.Println("Loading FE0")
+ m.latch_a = 0xFE
+ WriteVramBank(m.VromBanks, m.LatchFE0, 0x0000, Size4k)
+ case a == 0x1FD0 && m.latch_b != 0xFD:
+ fmt.Println("Loading FD1")
+ m.latch_b = 0xFD
+ WriteVramBank(m.VromBanks, m.LatchFD1, 0x1000, Size4k)
+ case a == 0x1FE0 && m.latch_b != 0xFE:
+ fmt.Println("Loading FE1")
+ m.latch_b = 0xFE
+ WriteVramBank(m.VromBanks, m.LatchFE1, 0x1000, Size4k)
}
}
@@ -122,18 +122,18 @@ func (m *Mmc2) BatteryBacked() bool {
}
func (m *Mmc2) RegisterNumber(a int) int {
- switch {
- case a >= 0xA000 && a <= 0xAFFF:
+ switch a >> 12 {
+ case 0xA:
return RegisterPrgBankSelect
- case a >= 0xB000 && a <= 0xBFFF:
+ case 0xB:
return RegisterChrBank1Select
- case a >= 0xC000 && a <= 0xCFFF:
+ case 0xC:
return RegisterChrBank2Select
- case a >= 0xD000 && a <= 0xDFFF:
+ case 0xD:
return RegisterChrBank3Select
- case a >= 0xE000 && a <= 0xEFFF:
+ case 0xE:
return RegisterChrBank4Select
- case a >= 0xF000 && a <= 0xFFFF:
+ case 0xF:
return RegisterMirroringSelect
}
@@ -146,30 +146,35 @@ func (m *Mmc2) PrgBankSelect(v Word) {
}
func (m *Mmc2) ChrBankSelect(v Word, b int) {
+
switch b {
case 1:
- m.Latch0Low = int(v)
+ fmt.Printf("Setting FD0 -> a = 0x%X\n", m.latch_a)
+ m.LatchFD0 = int(v)
- if m.Latch0 == 0xFD {
- WriteVramBank(m.VromBanks, m.Latch0Low, 0x0000, Size4k)
+ if m.latch_a == 0xFD {
+ WriteVramBank(m.VromBanks, m.LatchFD0%len(m.VromBanks), 0x0000, Size4k)
}
case 2:
- m.Latch1Low = int(v)
+ fmt.Printf("Setting FE0 -> a = 0x%X\n", m.latch_a)
+ m.LatchFE0 = int(v)
- if m.Latch0 == 0xFE {
- WriteVramBank(m.VromBanks, m.Latch1Low, 0x0000, Size4k)
+ if m.latch_a == 0xFE {
+ WriteVramBank(m.VromBanks, m.LatchFE0%len(m.VromBanks), 0x0000, Size4k)
}
case 3:
- m.Latch0High = int(v)
+ fmt.Printf("Setting FD1 -> b = 0x%X\n", m.latch_b)
+ m.LatchFD1 = int(v)
- if m.Latch1 == 0xFD {
- WriteVramBank(m.VromBanks, m.Latch0High, 0x1000, Size4k)
+ if m.latch_b == 0xFD {
+ WriteVramBank(m.VromBanks, m.LatchFD1%len(m.VromBanks), 0x1000, Size4k)
}
case 4:
- m.Latch1High = int(v)
+ fmt.Printf("Setting FE1 -> b = 0x%X\n", m.latch_b)
+ m.LatchFE1 = int(v)
- if m.Latch1 == 0xFE {
- WriteVramBank(m.VromBanks, m.Latch1High, 0x1000, Size4k)
+ if m.latch_b == 0xFE {
+ WriteVramBank(m.VromBanks, m.LatchFE1%len(m.VromBanks) , 0x1000, Size4k)
}
}
}
View
7 ppu.go
@@ -505,11 +505,6 @@ func (p *Ppu) WriteAddress(v Word) {
p.VramAddress = p.VramLatch
}
- if p.VramAddress < 0x2000 {
- // MMC2 latch trigger
- rom.LatchTrigger(p.VramAddress)
- }
-
p.checkA12RisingEdge()
p.WriteLatch = !p.WriteLatch
}
@@ -777,7 +772,7 @@ func (p *Ppu) evaluateScanlineSprites(line int) {
spriteCount++
- if spriteCount == 8 {
+ if spriteCount == 9 {
p.setStatus(StatusSpriteOverflow)
break
}
View
BIN test_roms/apu_mixer/source/common/ascii.chr
Binary file not shown.
View
92 test_roms/apu_mixer/source/common/build_rom.s
@@ -1,92 +0,0 @@
-; Builds program as iNES ROM
-
-; Default is 32K PRG and 8K CHR ROM, NROM (0)
-
-.if 0 ; Options to set before .include "shell.inc":
-CHR_RAM=1 ; Use CHR-RAM instead of CHR-ROM
-CART_WRAM=1 ; Use mapper that supports 8K WRAM in cart
-CUSTOM_MAPPER=n ; Specify mapper number
-.endif
-
-.ifndef CUSTOM_MAPPER
- .ifdef CART_WRAM
- CUSTOM_MAPPER = 2 ; UNROM
- .else
- CUSTOM_MAPPER = 0 ; NROM
- .endif
-.endif
-
-;;;; iNES header
-.ifndef CUSTOM_HEADER
- .segment "HEADER"
- .byte $4E,$45,$53,26 ; "NES" EOF
-
- .ifdef CHR_RAM
- .byte 2,0 ; 32K PRG, CHR RAM
- .else
- .byte 2,1 ; 32K PRG, 8K CHR
- .endif
-
- .byte CUSTOM_MAPPER*$10+$01 ; vertical mirroring
-.endif
-
-.ifndef CUSTOM_VECTORS
- .segment "VECTORS"
- .word -1,-1,-1, nmi, reset, irq
-.endif
-
-;;;; CHR-RAM/ROM
-.ifdef CHR_RAM
- .define CHARS "CHARS_PRG"
- .segment CHARS
- ascii_chr:
-
- .segment "CHARS_PRG_ASCII"
- .align $200
- .incbin "ascii.chr"
- ascii_chr_end:
-.else
- .define CHARS "CHARS"
- .segment "CHARS_ASCII"
- .align $200
- .incbin "ascii.chr"
- .res $1800
-.endif
-
-.segment CHARS
- .res $10,0
-
-;;;; Shell
-.ifndef NEED_CONSOLE
- NEED_CONSOLE=1
-.endif
-
-.segment "CODE"
- .res $4000
-
-.include "shell.s"
-
-std_reset:
- lda #0
- sta PPUCTRL
- sta PPUMASK
- jmp run_shell
-
-init_runtime:
- .ifdef CHR_RAM
- load_chr_ram
- .endif
- rts
-
-post_exit:
- jsr set_final_result
- jsr play_hex
- jmp forever
-
-; This helps devcart recover after running test.
-; It is never executed by test ROM.
-.segment "LOADER"
- .incbin "devcart.bin"
-
-.code
-.align 256
View
328 test_roms/apu_mixer/source/common/console.s
@@ -1,328 +0,0 @@
-; Scrolling text console with word wrapping, 30x29 characters.
-;
-; * Defers PPU initialization until first flush/ newline.
-; * Works even if PPU doesn't support scrolling.
-; * Keeps border around edge of screen for TV overscan.
-; * Requires vertical or single-screen mirroring.
-; * Requires ASCII font in CHR.
-
-.ifndef CONSOLE_COLOR
- CONSOLE_COLOR = $30 ; white
-.endif
-
-console_screen_width = 32 ; if lower than 32, left-justifies
-
-; Number of characters of margin on left and right, to avoid
-; text getting cut off by common TVs. OK if either/both are 0.
-console_left_margin = 1
-console_right_margin = 1
-
-console_width = console_screen_width - console_left_margin - console_right_margin
-
-zp_byte console_pos ; 0 to console_width
-zp_byte console_scroll
-zp_byte console_temp
-bss_res console_buf,console_width
-
-
-; Initializes console
-console_init:
- ; Flag that console hasn't been initialized
- setb console_scroll,-1
-
- setb console_pos,0
- rts
-
-
-; Hides console by disabling PPU rendering and blacking out
-; first four entries of palette.
-; Preserved: A, X, Y
-console_hide:
- pha
- jsr console_wait_vbl_
- setb PPUMASK,0
- lda #$0F
- jsr console_load_palette_
- pla
- rts
-
-
-; Shows console display
-; Preserved: A, X, Y
-console_show:
- pha
- lda #CONSOLE_COLOR
- jsr console_show_custom_color_
- pla
- rts
-
-
-; Prints char A to console. Will not appear until
-; a newline or flush occurs.
-; Preserved: A, X, Y
-console_print:
- cmp #10
- beq console_newline
-
- sty console_temp
-
- ldy console_pos
- cpy #console_width
- beq console_full_
- sta console_buf,y
- iny
- sty console_pos
-
- ldy console_temp
- rts
-
-
-; Displays current line and starts new one
-; Preserved: A, X, Y
-console_newline:
- pha
- jsr console_wait_vbl_
- jsr console_flush_
- jsr console_scroll_up_
- setb console_pos,0
- pla
- rts
-
-
-; Displays current line's contents without scrolling.
-; Preserved: A, X, Y
-console_flush:
- pha
- jsr console_wait_vbl_
- jsr console_flush_
- jsr console_apply_scroll_
- pla
- rts
-
-
-;**** Internal routines ****
-
-console_full_:
- ldy console_temp
-
- ; Line is full
-
- ; If space, treat as newline
- cmp #' '
- beq console_newline
-
- ; Wrap current line at appropriate point
- pha
- tya
- pha
- jsr console_wrap_
- pla
- tay
- pla
-
- jmp console_print
-
-
-; Inserts newline into buffer at appropriate position, leaving
-; next line ready in buffer
-; Preserved: X, console_temp
-console_wrap_:
- ; Find beginning of last word
- ldy #console_width
- lda #' '
-: dey
- bmi console_newline
- cmp console_buf,y
- bne :-
-
- ; y = 0 to console_width-1
-
- ; Flush through current word and put remaining
- ; in buffer for next line
- jsr console_wait_vbl_
-
- ; Time to last PPU write: 207 + 32*(26 + 10)
-
- lda console_scroll
- jsr console_set_ppuaddr_
-
- stx console_pos ; save X
-
- ldx #0
-
- ; Print everything before last word
-: lda console_buf,x
- sta PPUDATA
- inx
- dey
- bpl :-
-
- ; x = 1 to console_width
-
- ; Move last word to beginning of buffer, and
- ; print spaces for rest of line
- ldy #0
- beq :++
-: lda #' '
- sta PPUDATA
- lda console_buf,x
- inx
- sta console_buf,y
- iny
-: cpx #console_width
- bne :--
-
- ldx console_pos ; restore X
-
- ; Append new text after that
- sty console_pos
-
- ; FALL THROUGH
-
-
-; Scrolls up 8 pixels and clears one line BELOW new line
-; Preserved: X, console_temp
-console_scroll_up_:
- ; Scroll up 8 pixels
- lda console_scroll
- jsr console_add_8_to_scroll_
- sta console_scroll
-
- ; Clear line AFTER that on screen
- jsr console_add_8_to_scroll_
- jsr console_set_ppuaddr_
-
- ldy #console_width
- lda #' '
-: sta PPUDATA
- dey
- bne :-
- ; FALL THROUGH
-
-
-; Applies current scrolling position to PPU
-; Preserved: X, Y, console_temp
-console_apply_scroll_:
- lda #0
- sta PPUADDR
- sta PPUADDR
-
- sta PPUSCROLL
- lda console_scroll
- jsr console_add_8_to_scroll_
- jsr console_add_8_to_scroll_
- sta PPUSCROLL
- rts
-
-
-; Sets PPU address for row
-; In: A = scroll position
-; Preserved: X, Y
-console_set_ppuaddr_:
- sta console_temp
- lda #$08
- asl console_temp
- rol a
- asl console_temp
- rol a
- sta PPUADDR
- lda console_temp
- ora #console_left_margin
- sta PPUADDR
- rts
-
-
-; A = (A + 8) % 240
-; Preserved: X, Y
-console_add_8_to_scroll_:
- cmp #240-8
- bcc :+
- adc #16-1;+1 for set carry
-: adc #8
- rts
-
-
-console_show_custom_color_:
- pha
- jsr console_wait_vbl_
- setb PPUMASK,PPUMASK_BG0
- pla
- jsr console_load_palette_
- jmp console_apply_scroll_
-
-
-console_load_palette_:
- pha
- setb PPUADDR,$3F
- setb PPUADDR,$00
- setb PPUDATA,$0F ; black
- pla
- sta PPUDATA
- sta PPUDATA
- sta PPUDATA
- rts
-
-
-; Initializes PPU if necessary, then waits for VBL
-; Preserved: A, X, Y, console_temp
-console_wait_vbl_:
- lda console_scroll
- cmp #-1
- bne @already_initialized
-
- ; Deferred initialization of PPU until first use of console
-
- ; In case PPU doesn't support scrolling, start a
- ; couple of lines down
- setb console_scroll,16
-
- jsr console_hide
- tya
- pha
-
- ; Fill nametable with spaces
- setb PPUADDR,$20
- setb PPUADDR,$00
- ldy #240
- lda #' '
-: sta PPUDATA
- sta PPUDATA
- sta PPUDATA
- sta PPUDATA
- dey
- bne :-
-
- ; Clear attributes
- lda #0
- ldy #$40
-: sta PPUDATA
- dey
- bne :-
-
- pla
- tay
-
- jsr console_show
-@already_initialized:
- jmp wait_vbl_optional
-
-
-; Flushes current line
-; Preserved: X, Y
-console_flush_:
- lda console_scroll
- jsr console_set_ppuaddr_
-
- sty console_temp
-
- ; Copy line
- ldy #0
- beq :++
-: lda console_buf,y
- sta PPUDATA
- iny
-: cpy console_pos
- bne :--
-
- ldy console_temp
- rts
View
118 test_roms/apu_mixer/source/common/crc.s
@@ -1,118 +0,0 @@
-; CRC-32 checksum calculation
-
-zp_res checksum,4
-zp_byte checksum_temp
-zp_byte checksum_off_
-
-; Turns CRC updating on/off. Allows nesting.
-; Preserved: A, X, Y
-crc_off:
- dec checksum_off_
- rts
-
-crc_on: inc checksum_off_
- beq :+
- jpl internal_error ; catch unbalanced crc calls
-: rts
-
-
-; Initializes checksum module. Might initialize tables
-; in the future.
-init_crc:
- jmp reset_crc
-
-
-; Clears checksum and turns it on
-; Preserved: X, Y
-reset_crc:
- lda #0
- sta checksum_off_
- lda #$FF
- sta checksum
- sta checksum + 1
- sta checksum + 2
- sta checksum + 3
- rts
-
-
-; Updates checksum with byte in A (unless disabled via crc_off)
-; Preserved: A, X, Y
-; Time: 357 clocks average
-update_crc:
- bit checksum_off_
- bmi update_crc_off
-update_crc_:
- pha
- stx checksum_temp
- eor checksum
- ldx #8
-@bit: lsr checksum+3
- ror checksum+2
- ror checksum+1
- ror a
- bcc :+
- sta checksum
- lda checksum+3
- eor #$ED
- sta checksum+3
- lda checksum+2
- eor #$B8
- sta checksum+2
- lda checksum+1
- eor #$83
- sta checksum+1
- lda checksum
- eor #$20
-: dex
- bne @bit
- sta checksum
- ldx checksum_temp
- pla
-update_crc_off:
- rts
-
-
-; Prints checksum as 8-character hex value
-print_crc:
- jsr crc_off
-
- ; Print complement
- ldx #3
-: lda checksum,x
- eor #$FF
- jsr print_hex
- dex
- bpl :-
-
- jmp crc_on
-
-
-; EQ if checksum matches CRC
-; Out: A=0 and EQ if match, A>0 and NE if different
-; Preserved: X, Y
-.macro is_crc crc
- jsr_with_addr is_crc_,{.dword crc}
-.endmacro
-
-is_crc_:
- tya
- pha
-
- ; Compare with complemented checksum
- ldy #3
-: lda (ptr),y
- sec
- adc checksum,y
- bne @wrong
- dey
- bpl :-
- pla
- tay
- lda #0
- rts
-
-@wrong:
- pla
- tay
- lda #1
- rts
View
190 test_roms/apu_mixer/source/common/delay.s
@@ -1,190 +0,0 @@
-; Delays in CPU clocks, milliseconds, etc. All routines are re-entrant
-; (no global data). No routines touch X or Y during execution.
-; Code generated by macros is relocatable; it contains no JMPs to itself.
-
-zp_byte delay_temp_ ; only written to
-
-; Delays n clocks, from 2 to 16777215
-; Preserved: A, X, Y, flags
-.macro delay n
- .if (n) < 0 .or (n) = 1 .or (n) > 16777215
- .error "Delay out of range"
- .endif
- delay_ (n)
-.endmacro
-
-
-; Delays n milliseconds (1/1000 second)
-; n can range from 0 to 1100.
-; Preserved: A, X, Y, flags
-.macro delay_msec n
- .if (n) < 0 .or (n) > 1100
- .error "time out of range"
- .endif
- delay ((n)*CLOCK_RATE+500)/1000
-.endmacro
-
-
-; Delays n microseconds (1/1000000 second).
-; n can range from 0 to 100000.
-; Preserved: A, X, Y, flags
-.macro delay_usec n
- .if (n) < 0 .or (n) > 100000
- .error "time out of range"
- .endif
- delay ((n)*((CLOCK_RATE+50)/100)+5000)/10000
-.endmacro
-
-.align 64
-
-; Delays A clocks + overhead
-; Preserved: X, Y
-; Time: A+25 clocks (including JSR)
-: sbc #7 ; carry set by CMP
-delay_a_25_clocks:
- cmp #7
- bcs :- ; do multiples of 7
- lsr a ; bit 0
- bcs :+
-: ; A=clocks/2, either 0,1,2,3
- beq @zero ; 0: 5
- lsr a
- beq :+ ; 1: 7
- bcc :+ ; 2: 9
-@zero: bne :+ ; 3: 11
-: rts ; (thanks to dclxvi for the algorithm)
-
-
-; Delays A*256 clocks + overhead
-; Preserved: X, Y
-; Time: A*256+16 clocks (including JSR)
-delay_256a_16_clocks:
- cmp #0
- bne :+
- rts
-delay_256a_11_clocks_:
-: pha
- lda #256-19-22
- jsr delay_a_25_clocks
- pla
- clc
- adc #-1
- bne :-
- rts
-
-
-; Delays A*65536 clocks + overhead
-; Preserved: X, Y
-; Time: A*65536+16 clocks (including JSR)
-delay_65536a_16_clocks:
- cmp #0
- bne :+
- rts
-delay_65536a_11_clocks_:
-: pha
- lda #256-19-22-13
- jsr delay_a_25_clocks
- lda #255
- jsr delay_256a_11_clocks_
- pla
- clc
- adc #-1
- bne :-
- rts
-
-max_short_delay = 41
-
- ; delay_short_ macro jumps into these
- .res (max_short_delay-12)/2,$EA ; NOP
-delay_unrolled_:
- rts
-
-.macro delay_short_ n
- .if n < 0 .or n = 1 .or n > max_short_delay
- .error "Internal delay error"
- .endif
- .if n = 0
- ; nothing
- .elseif n = 2
- nop
- .elseif n = 3
- sta <delay_temp_
- .elseif n = 4
- nop
- nop
- .elseif n = 5
- sta <delay_temp_
- nop
- .elseif n = 6
- nop
- nop
- nop
- .elseif n = 7
- php
- plp
- .elseif n = 8
- nop
- nop
- nop
- nop
- .elseif n = 9
- php
- plp
- nop
- .elseif n = 10
- sta <delay_temp_
- php
- plp
- .elseif n = 11
- php
- plp
- nop
- nop
- .elseif n = 13
- php
- plp
- nop
- nop
- nop
- .elseif n & 1
- sta <delay_temp_
- jsr delay_unrolled_-((n-15)/2)
- .else
- jsr delay_unrolled_-((n-12)/2)
- .endif
-.endmacro
-
-.macro delay_nosave_ n
- ; 65536+17 = maximum delay using delay_256a_11_clocks_
- ; 255+27 = maximum delay using delay_a_25_clocks
- ; 27 = minimum delay using delay_a_25_clocks
- .if n > 65536+17
- lda #^(n - 15)
- jsr delay_65536a_11_clocks_
- ; +2 ensures remaining clocks is never 1
- delay_nosave_ (((n - 15) & $FFFF) + 2)
- .elseif n > 255+27
- lda #>(n - 15)
- jsr delay_256a_11_clocks_
- ; +2 ensures remaining clocks is never 1
- delay_nosave_ (<(n - 15) + 2)
- .elseif n >= 27
- lda #<(n - 27)
- jsr delay_a_25_clocks
- .else
- delay_short_ n
- .endif
-.endmacro
-
-.macro delay_ n
- .if n > max_short_delay
- php
- pha
- delay_nosave_ (n - 14)
- pla
- plp
- .else
- delay_short_ n
- .endif
-.endmacro
-
View
BIN test_roms/apu_mixer/source/common/devcart.bin
Binary file not shown.
View
188 test_roms/apu_mixer/source/common/macros.inc
@@ -1,188 +0,0 @@
-; jxx equivalents to bxx
-.macpack longbranch
-
-; blt, bge equivalents to bcc, bcs
-.define blt bcc
-.define bge bcs
-.define jge jcs
-.define jlt jcc
-
-; Puts data in another segment
-.macro seg_data seg,data
- .pushseg
- .segment seg
- data
- .popseg
-.endmacro
-
-; Reserves size bytes in zeropage/bss for name.
-; If size is omitted, reserves one byte.
-.macro zp_res name,size
- .ifblank size
- zp_res name,1
- .else
- seg_data "ZEROPAGE",{name: .res size}
- .endif
-.endmacro
-
-.macro bss_res name,size
- .ifblank size
- bss_res name,1
- .else
- seg_data "BSS",{name: .res size}
- .endif
-.endmacro
-
-.macro nv_res name,size
- .ifblank size
- nv_res name,1
- .else
- seg_data "NVRAM",{name: .res size}
- .endif
-.endmacro
-
-; Reserves one byte in zeropage for name (very common)
-.macro zp_byte name
- seg_data "ZEROPAGE",{name: .res 1}
-.endmacro
-
-; Passes constant data to routine in addr
-; Preserved: A, X, Y
-.macro jsr_with_addr routine,data
- .local Addr
- pha
- lda #<Addr
- sta addr
- lda #>Addr
- sta addr+1
- pla
- jsr routine
- seg_data "RODATA",{Addr: data}
-.endmacro
-
-; Calls routine multiple times, with A having the
-; value 'start' the first time, 'start+step' the
-; second time, up to 'end' for the last time.
-.macro for_loop routine,start,end,step
- lda #start
-: pha
- jsr routine
- pla
- clc
- adc #step
- cmp #<((end)+(step))
- bne :-
-.endmacro
-
-; Calls routine n times. The value of A in the routine
-; counts from 0 to n-1.
-.macro loop_n_times routine,n
- for_loop routine,0,n-1,+1
-.endmacro
-
-; Same as for_loop, except uses 16-bit value in YX.
-; -256 <= step <= 255
-.macro for_loop16 routine,start,end,step
-.if (step) < -256 || (step) > 255
- .error "Step must be within -256 to 255"
-.endif
- ldy #>(start)
- lda #<(start)
-: tax
- pha
- tya
- pha
- jsr routine
- pla
- tay
- pla
- clc
- adc #step
-.if (step) > 0
- bcc :+
- iny
-.else
- bcs :+
- dey
-.endif
-: cmp #<((end)+(step))
- bne :--
- cpy #>((end)+(step))
- bne :--
-.endmacro
-
-; Copies byte from in to out
-; Preserved: X, Y
-.macro mov out, in
- lda in
- sta out
-.endmacro
-
-; Stores byte at addr
-; Preserved: X, Y
-.macro setb addr, byte
- lda #byte
- sta addr
-.endmacro
-
-; Stores word at addr
-; Preserved: X, Y
-.macro setw addr, word
- lda #<(word)
- sta addr
- lda #>(word)
- sta addr+1
-.endmacro
-
-; Loads XY with 16-bit immediate or value at address
-.macro ldxy Arg
- .if .match( .left( 1, {Arg} ), # )
- ldy #<(.right( .tcount( {Arg} )-1, {Arg} ))
- ldx #>(.right( .tcount( {Arg} )-1, {Arg} ))
- .else
- ldy (Arg)
- ldx (Arg)+1
- .endif
-.endmacro
-
-; Increments word at Addr and sets Z flag appropriately
-; Preserved: A, X, Y
-.macro incw Addr
- .local @incw_skip ; doesn't work, so HOW THE HELL DO YOU MAKE A LOCAL LABEL IN A MACRO THAT DOESN"T DISTURB INVOKING CODE< HUH?????? POS
- inc Addr
- bne @incw_skip
- inc Addr+1
-@incw_skip:
-.endmacro
-
-; Increments XY as 16-bit register, in CONSTANT time.
-; Z flag set based on entire result.
-; Preserved: A
-; Time: 7 clocks
-.macro inxy
- iny ; 2
- beq *+4 ; 3
- ; -1
- bne *+3 ; 3
- ; -1
- inx ; 2
-.endmacro
-
-; Negates A and adds it to operand
-.macro subaf Operand
- eor #$FF
- sec
- adc Operand
-.endmacro
-
-; Initializes CPU registers to reasonable values
-.macro init_cpu_regs
- sei
- cld ; unnecessary on NES, but might help on clone
- ldx #$FF
- txs
- .ifndef BUILD_NSF
- inx
- stx PPUCTRL
- .endif
-.endmacro
View
56 test_roms/apu_mixer/source/common/neshw.inc
@@ -1,56 +0,0 @@
-; NES I/O locations and masks
-
-.ifndef BUILD_NSF
-
-; PPU
-PPUCTRL = $2000
-PPUMASK = $2001
-PPUSTATUS = $2002
-SPRADDR = $2003
-SPRDATA = $2004
-PPUSCROLL = $2005
-PPUADDR = $2006
-PPUDATA = $2007
-SPRDMA = $4014
-
-PPUCTRL_NMI = $80
-PPUMASK_BG0 = $0A
-PPUCTRL_8X8 = $00
-PPUCTRL_8X16 = $20
-PPUMASK_SPR = $14
-PPUMASK_BG0CLIP = $08
-
-.endif
-
-; APU
-SNDCHN = $4015
-JOY1 = $4016
-JOY2 = $4017
-SNDMODE = $4017
-
-SNDMODE_NOIRQ = $40
-
-.ifndef REGION_FREE
- .ifndef PAL_ONLY
- .ifndef NTSC_ONLY
- NTSC_ONLY = 1
- .endif
- .endif
-.else
- .ifdef NTSC_ONLY
- .error "NTSC_ONLY and REGION_FREE defined"
- .endif
- .ifdef PAL_ONLY
- .error "PAL_ONLY and REGION_FREE defined"
- .endif
-.endif
-
-.ifdef NTSC_ONLY
- CLOCK_RATE = 1789773
- PPU_FRAMELEN = 29781
-.endif
-
-.ifdef PAL_ONLY
- CLOCK_RATE = 1662607
- PPU_FRAMELEN = 33248
-.endif
View
203 test_roms/apu_mixer/source/common/ppu.s
@@ -1,203 +0,0 @@
-; PPU utilities
-
-bss_res ppu_not_present
-
-; Sets PPUADDR to w
-; Preserved: X, Y
-.macro set_ppuaddr w
- bit PPUSTATUS
- setb PPUADDR,>w
- setb PPUADDR,<w
-.endmacro
-
-
-; Delays by no more than n scanlines
-.macro delay_scanlines n
- .if CLOCK_RATE <> 1789773
- .error "Currently only supports NTSC"
- .endif
- delay ((n)*341)/3
-.endmacro
-
-
-; Waits for VBL then disables PPU rendering.
-; Preserved: A, X, Y
-disable_rendering:
- pha
- jsr wait_vbl_optional
- setb PPUMASK,0
- pla
- rts
-
-
-; Fills first nametable with $00
-; Preserved: Y
-clear_nametable:
- ldx #$20
- bne clear_nametable_
-
-clear_nametable2:
- ldx #$24
-clear_nametable_:
- lda #0
- jsr fill_screen_
-
- ; Clear pattern table
- ldx #64
-: sta PPUDATA
- dex
- bne :-
- rts
-
-
-; Fills screen with tile A
-; Preserved: A, Y
-fill_screen:
- ldx #$20
- bne fill_screen_
-
-; Same as fill_screen, but fills other nametable
-fill_screen2:
- ldx #$24
-fill_screen_:
- stx PPUADDR
- ldx #$00
- stx PPUADDR
- ldx #240
-: sta PPUDATA
- sta PPUDATA
- sta PPUDATA
- sta PPUDATA
- dex
- bne :-
- rts
-
-
-; Fills palette with $0F
-; Preserved: Y
-clear_palette:
- set_ppuaddr $3F00
- ldx #$20
- lda #$0F
-: sta PPUDATA
- dex
- bne :-
-
-
-; Fills OAM with $FF
-; Preserved: Y
-clear_oam:
- lda #$FF
-
-; Fills OAM with A
-; Preserved: A, Y
-fill_oam:
- ldx #0
- stx SPRADDR
-: sta SPRDATA
- dex
- bne :-
- rts
-
-
-; Initializes wait_vbl_optional. Must be called before
-; using it.
-.align 32
-init_wait_vbl:
- ; Wait for VBL flag to be set, or ~60000
- ; clocks (2 frames) to pass
- ldy #24
- ldx #1
- bit PPUSTATUS
-: bit PPUSTATUS
- bmi @set
- dex
- bne :-
- dey
- bpl :-
-@set:
- ; Be sure flag didn't stay set (in case
- ; PPUSTATUS always has high bit set)
- tya
- ora PPUSTATUS
- sta ppu_not_present
- rts
-
-
-; Same as wait_vbl, but returns immediately if PPU
-; isn't working or doesn't support VBL flag
-; Preserved: A, X, Y
-.align 16
-wait_vbl_optional:
- bit ppu_not_present
- bmi :++
- ; FALL THROUGH
-
-; Clears VBL flag then waits for it to be set.
-; Preserved: A, X, Y
-wait_vbl:
- bit PPUSTATUS
-: bit PPUSTATUS
- bpl :-
-: rts
-
-
-.macro check_ppu_region_ Len
- ; Delays since VBL began
- jsr wait_vbl_optional ; 10 average
- delay Len - 18 - 200
- lda PPUSTATUS ; 4
- bmi @ok ; 2
- delay 200
- ; Next VBL should roughly begin here if it's the
- ; one we are detecting
- delay 200
- lda PPUSTATUS ; 2
- bpl @ok
-.endmacro
-
-check_ppu_region:
-
-.ifndef REGION_FREE
-.ifdef PAL_ONLY
- check_ppu_region_ 29781
- print_str {newline,"Note: This test is meant for PAL NES only.",newline,newline}
-.endif
-
-.ifdef NTSC_ONLY
- check_ppu_region_ 33248
- print_str {newline,"Note: This test is meant for NTSC NES only.",newline,newline}
-.endif
-.endif
-@ok: rts
-
-
-; Loads ASCII font into CHR RAM and fills rest with $FF
-.macro load_chr_ram
- bit PPUSTATUS
- setb PPUADDR,0
- setb PPUADDR,0
-
- ; Copy ascii_chr to 0
- setb addr,<ascii_chr
- ldx #>ascii_chr
- ldy #0
-@page:
- stx addr+1
-: lda (addr),y
- sta PPUDATA
- iny
- bne :-
- inx
- cpx #>ascii_chr_end
- bne @page
-
- ; Fill rest
- lda #$FF
-: sta PPUDATA
- iny
- bne :-
- inx
- cpx #$20
- bne :-
-.endmacro
View
247 test_roms/apu_mixer/source/common/print.s
@@ -1,247 +0,0 @@
-; Prints values in various ways to output,
-; including numbers and strings.
-
-newline = 10
-
-zp_byte print_temp_
-
-; Prints indicated register to console as two hex
-; chars and space
-; Preserved: A, X, Y, flags
-print_a:
- php
- pha
-print_reg_:
- jsr print_hex
- lda #' '
- jsr print_char_
- pla
- plp
- rts
-
-print_x:
- php
- pha
- txa
- jmp print_reg_
-
-print_y:
- php
- pha
- tya
- jmp print_reg_
-
-print_p:
- php
- pha
- php
- pla
- jmp print_reg_
-
-print_s:
- php
- pha
- txa
- tsx
- inx
- inx
- inx
- inx
- jsr print_x
- tax
- pla
- plp
- rts
-
-
-; Prints A as two hex characters, NO space after
-; Preserved: A, X, Y
-print_hex:
- jsr update_crc
-
- pha
- lsr a
- lsr a
- lsr a
- lsr a
- jsr print_nibble_
- pla
-
- pha
- and #$0F
- jsr print_nibble_
- pla
- rts
-
-print_nibble_:
- cmp #10
- blt @digit
- adc #6;+1 since carry is set
-@digit: adc #'0'
- jmp print_char_
-
-
-; Prints low 4 bits of A as single hex character
-; Preserved: A, X, Y
-print_nibble:
- pha
- and #$0F
- jsr update_crc
- jsr print_nibble_
- pla
- rts
-
-
-; Prints character and updates checksum UNLESS
-; it's a newline.
-; Preserved: A, X, Y
-print_char:
- cmp #newline
- beq :+
- jsr update_crc
-: pha
- jsr print_char_
- pla
- rts
-
-
-; Prints space. Does NOT update checksum.
-; Preserved: A, X, Y
-print_space:
- pha
- lda #' '
- jsr print_char_
- pla
- rts
-
-
-; Advances to next line. Does NOT update checksum.
-; Preserved: A, X, Y
-print_newline:
- pha
- lda #newline
- jsr print_char_
- pla
- rts
-
-
-; Prints string
-; Preserved: A, X, Y
-.macro print_str str,str2
- jsr print_str_
- .byte str
- .ifnblank str2
- .byte str2
- .endif
- .byte 0
-.endmacro
-
-
-print_str_:
- sta print_temp_
-
- pla
- sta addr
- pla
- sta addr+1
-
- jsr inc_addr
- jsr print_str_addr
-
- lda print_temp_
- jmp (addr)
-
-
-; Prints string at addr and leaves addr pointing to
-; byte AFTER zero terminator.
-; Preserved: A, X, Y
-print_str_addr:
- pha
- tya
- pha
-
- ldy #0
- beq :+ ; always taken
-@loop: jsr print_char
- jsr inc_addr
-: lda (addr),y
- bne @loop
-
- pla
- tay
- pla
- ; FALL THROUGH
-
-; Increments 16-bit value in addr.
-; Preserved: A, X, Y
-inc_addr:
- inc addr
- beq :+
- rts
-: inc addr+1
- rts
-
-
-; Prints A as 1-3 digit decimal value, NO space after.
-; Preserved: A, X, Y
-print_dec:
- pha
- sta print_temp_
- jsr update_crc
- txa
- pha
- lda print_temp_
-
- ; Hundreds
- cmp #10
- blt @ones
- cmp #100
- blt @tens
- ldx #'0'-1
-: inx
- sbc #100
- bge :-
- adc #100
- jsr @digit
-
- ; Tens
-@tens: sec
- ldx #'0'-1
-: inx
- sbc #10
- bge :-
- adc #10
- jsr @digit
-
- ; Ones
-@ones: ora #'0'
- jsr print_char
- pla
- tax
- pla
- rts
-
- ; Print a single digit
-@digit: pha
- txa
- jsr print_char
- pla
- rts
-
-
-; Prints one of two characters based on condition.
-; SEC; print_cc bcs,'C','-' prints 'C'.
-; Preserved: A, X, Y, flags
-.macro print_cc cond,yes,no
- ; Avoids labels since they're not local
- ; to macros in ca65.
- php
- pha
- cond *+6
- lda #no
- bne *+4
- lda #yes
- jsr print_char
- pla
- plp
-.endmacro
View
32 test_roms/apu_mixer/source/common/shell.inc
@@ -1,32 +0,0 @@
-; Included at beginning of program
-
-.ifdef CUSTOM_PREFIX
- .include "custom_prefix.s"
-.endif
-
-; Sub-test in a multi-test ROM
-.ifdef BUILD_MULTI
- .include "build_multi.s"
-.else
-
-; NSF music file
-.ifdef BUILD_NSF
- .include "build_nsf.s"
-.endif
-
-; Devcart
-.ifdef BUILD_DEVCART
- .include "build_devcart.s"
-.endif
-
-; NES internal RAM
-.ifdef BUILD_NOCART
- .include "build_nocart.s"
-.endif
-
-; NES ROM (default)
-.ifndef SHELL_INCLUDED
- .include "build_rom.s"
-.endif
-
-.endif ; .ifdef BUILD_MULTI
View
180 test_roms/apu_mixer/source/common/shell.s
@@ -1,180 +0,0 @@
-; Shell that sets up testing framework and calls main
-
-; Detect inclusion loops (otherwise ca65 goes crazy)
-.ifdef SHELL_INCLUDED
- .error "shell.s included twice"
- .end
-.endif
-SHELL_INCLUDED = 1
-
-; Temporary variables that ANY routine might modify, so
-; only use them between routine calls.
-temp = <$A
-temp2 = <$B
-temp3 = <$C
-addr = <$E
-ptr = addr
-
-; Move code from $C000 to $E200, to accommodate my devcarts
-.segment "CODE"
- .res $2200
-
-; Put shell code after user code, so user code is in more
-; consistent environment
-.segment "CODE2"
-
- ; Any user code which runs off end might end up here,
- ; so catch that mistake.
- nop ; in case there was three-byte opcode before this
- nop
- jmp internal_error
-
-;**** Common routines ****
-
-.include "macros.inc"
-.include "neshw.inc"
-.include "delay.s"
-.include "print.s"
-.include "crc.s"
-.include "testing.s"
-
-;**** Shell core ****
-
-.ifndef CUSTOM_RESET
- reset:
- sei
- jmp std_reset
-.endif
-
-
-; Sets up hardware then runs main
-run_shell:
- init_cpu_regs
-
- jsr init_shell
- set_test $FF
- jmp run_main
-
-
-; Initializes shell without affecting current set_test values
-init_shell:
- jsr clear_ram
- jsr init_wait_vbl ; waits for VBL once here,
- jsr wait_vbl_optional ; so only need to wait once more
- jsr init_text_out
- jsr init_testing
- jsr init_runtime
- jsr console_init
- rts
-
-
-; Runs main in consistent PPU/APU environment, then exits
-; with code 0
-run_main:
- jsr pre_main
- jsr main
- lda #0
- jmp exit
-
-
-; Sets up environment for main to run in
-pre_main:
-
-.ifndef BUILD_NSF
- jsr disable_rendering
- setb PPUCTRL,0
- jsr clear_palette
- jsr clear_nametable
- jsr clear_nametable2
- jsr clear_oam
-.endif
-
- ; Clear APU registers
- lda #0
- sta $4015
- ldx #$13
-: sta $4000,x
- dex
- bpl :-
-
- ; CPU registers
- lda #$34
- pha
- lda #0
- tax
- tay
- jsr wait_vbl_optional
- plp
- sta SNDMODE
- rts
-
-
-.ifndef CUSTOM_EXIT
- exit:
-.endif
-
-; Reports result and ends program
-std_exit:
- sta temp
- init_cpu_regs
- setb SNDCHN,0
- lda temp
-
- jsr report_result
- pha
- jsr check_ppu_region
- pla
- jmp post_exit
-
-
-; Reports final result code in A
-report_result:
- jsr :+
- jmp play_byte
-
-: jsr print_newline
- jsr console_show
-
- ; 0: ""
- cmp #1
- bge :+
- rts
-:
- ; 1: "Failed"
- bne :+
- print_str {"Failed",newline}
- rts
-
- ; n: "Failed #n"
-: print_str "Failed #"
- jsr print_dec
- jsr print_newline
- rts
-
-;**** Other routines ****
-
-.include "shell_misc.s"
-
-.ifdef NEED_CONSOLE
- .include "console.s"
-.else
- ; Stubs so code doesn't have to care whether
- ; console exists
- console_init:
- console_show:
- console_hide:
- console_print:
- console_flush:
- rts
-.endif
-
-.ifndef CUSTOM_PRINT
- .include "text_out.s"
-
- print_char_:
- jsr write_text_out
- jmp console_print
-
- stop_capture:
- rts
-.endif
View
211 test_roms/apu_mixer/source/common/shell_misc.s
@@ -1,211 +0,0 @@
-; Reports internal error and exits program
-internal_error:
- print_str newline,"Internal error"
- lda #255
- jmp exit
-
-.import __NVRAM_LOAD__, __NVRAM_SIZE__
-
-.macro fill_ram_ Begin, End
- ; Simpler to count from negative size up to 0,
- ; and adjust address downward to compensate
- ; for initial low byte in Y index
- .local Neg_size
- Neg_size = (Begin) - (End)
- ldxy #(Begin) - <Neg_size
- sty addr
- stx addr+1
- ldxy #Neg_size
-: sta (addr),y
- iny
- bne :-
- inc addr+1
- inx
- bne :-
-.endmacro
-
-; Clears 0 through ($100+S), $200 through __NVRAM_LOAD__-1, and
-; __NVRAM_LOAD__+__NVRAM_SIZE__ through $7FF
-clear_ram:
- lda #0
-
- bss_begin = $200
-
- fill_ram_ bss_begin,__NVRAM_LOAD__
- fill_ram_ __NVRAM_LOAD__+__NVRAM_SIZE__,$800
-
- ; Zero-page
- tax
-: sta 0,x
- inx
- bne :-
-
- ; Stack below S
- tsx
- inx
-: dex
- sta $100,x
- bne :-
-
- rts
-
-
-nv_res unused_nv_var ; to avoid size=0
-
-; Clears nvram
-clear_nvram:
- lda #0
- fill_ram_ __NVRAM_LOAD__,__NVRAM_LOAD__+__NVRAM_SIZE__
- rts
-
-
-; Prints filename and newline, if available, otherwise nothing.
-; Preserved: A, X, Y
-print_filename:
- .ifdef FILENAME_KNOWN
- pha
- jsr print_newline
- setw addr,filename
- jsr print_str_addr
- jsr print_newline
- pla
- .endif
- rts
-
-.pushseg
-.segment "RODATA"
- ; Filename terminated with zero byte.
- filename:
- .ifdef FILENAME_KNOWN
- .incbin "ram:nes_temp"
- .endif
- .byte 0
-.popseg
-
-
-;**** ROM-specific ****
-.ifndef BUILD_NSF
-
-.include "ppu.s"
-
-avoid_silent_nsf:
-play_byte:
- rts
-
-; Disables interrupts and loops forever
-.ifndef CUSTOM_FOREVER
-forever:
- sei
- lda #0
- sta PPUCTRL
-: beq :-
- .res $10,$EA ; room for code to run loader
-.endif
-
-
-; Default NMI
-.ifndef CUSTOM_NMI
- zp_byte nmi_count
- zp_byte flags_from_nmi
- zp_byte pclo_from_nmi
-
- nmi: ; Record flags and PC low byte from stack
- pla
- sta flags_from_nmi
- pla
- sta pclo_from_nmi
- pha
- lda flags_from_nmi
- pha
- inc nmi_count
- rti
-
- ; Waits for NMI. Must be using NMI handler that increments
- ; nmi_count, with NMI enabled.
- ; Preserved: X, Y
- wait_nmi:
- lda nmi_count
- : cmp nmi_count
- beq :-
- rts
-.endif
-
-
-; Default IRQ
-.ifndef CUSTOM_IRQ
- zp_byte flags_from_irq
- zp_byte pclo_from_irq
- zp_byte irq_count
-
- irq: ; Record flags and PC low byte from stack
- pla
- sta flags_from_irq
- pla
- sta pclo_from_irq
- pha
- lda flags_from_irq
- pha
- inc irq_count
- bit SNDCHN ; clear frame IRQ flag
- rti
-
-.endif
-
-.endif
-
-
-; Reports A in binary as high and low tones, with
-; leading low tone for reference. Omits leading
-; zeroes. Doesn't hang if no APU is present.
-; Preserved: A, X, Y
-play_hex:
- pha
-
- ; Make low reference beep
- clc
- jsr @beep
-
- ; Remove high zero bits
- sec
-: rol a
- bcc :-
-
- ; Play remaining bits
- beq @zero
-: jsr @beep
- asl a
- bne :-
-@zero:
-
- delay_msec 300
- pla
- rts
-
-; Plays low/high beep based on carry
-; Preserved: A, X, Y
-@beep:
- pha
-
- ; Set up square
- lda #1
- sta SNDCHN
- sta $4001
- sta $4003
- adc #$FE ; period=$100 if carry, $1FF if none
- sta $4002
-
- ; Fade volume
- lda #$0F
-: ora #$30
- sta $4000
- delay_msec 8
- sec
- sbc #$31
- bpl :-
-
- ; Silence
- setb SNDCHN,0
- delay_msec 160
-
- pla
- rts
View
105 test_roms/apu_mixer/source/common/testing.s
@@ -1,105 +0,0 @@
-; Utilities for writing test ROMs
-
-; In NVRAM so these can be used before initializing runtime,
-; then runtime initialized without clearing them
-nv_res test_code ; code of current test
-nv_res test_name,2 ; address of name of current test, or 0 of none
-
-
-; Sets current test code and optional name. Also resets
-; checksum.
-; Preserved: A, X, Y
-.macro set_test code,name
- pha
- lda #code
- jsr set_test_
- .ifblank name
- setb test_name+1,0
- .else
- .local Addr
- setw test_name,Addr
- seg_data "RODATA",{Addr: .byte name,0}
- .endif
- pla
-.endmacro
-
-set_test_:
- sta test_code
- jmp reset_crc
-
-
-; Initializes testing module
-init_testing = init_crc
-
-
-; Reports that all tests passed
-tests_passed:
- jsr print_filename
- print_str newline,"Passed"
- lda #0
- jmp exit
-
-
-; Reports "Done" if set_test has never been used,
-; "Passed" if set_test 0 was last used, or
-; failure if set_test n was last used.
-tests_done:
- ldx test_code
- jeq tests_passed
- inx
- bne test_failed
- jsr print_filename
- print_str newline,"Done"
- lda #0
- jmp exit
-
-
-; Reports that the current test failed. Prints code and
-; name last set with set_test, or just "Failed" if none
-; have been set yet.
-test_failed:
- ldx test_code
-
- ; Treat $FF as 1, in case it wasn't ever set
- inx
- bne :+
- inx
- stx test_code
-:
- ; If code >= 2, print name
- cpx #2-1 ; -1 due to inx above
- blt :+
- lda test_name+1
- beq :+
- jsr print_newline
- sta addr+1
- lda test_name
- sta addr
- jsr print_str_addr
- jsr print_newline
-:
- jsr print_filename
-
- ; End program
- lda test_code
- jmp exit
-
-
-; If checksum doesn't match expected, reports failed test.
-; Clears checksum afterwards.
-; Preserved: A, X, Y
-.macro check_crc expected
- jsr_with_addr check_crc_,{.dword expected}
-.endmacro
-
-check_crc_:
- pha
- jsr is_crc_
- bne :+
- jsr reset_crc
- pla
- rts
-
-: jsr print_newline
- jsr print_crc
- jmp test_failed
View
61 test_roms/apu_mixer/source/common/text_out.s
@@ -1,61 +0,0 @@
-; Text output as expanding zero-terminated string at text_out_base
-
-; The final exit result byte is written here
-final_result = $6000
-
-; Text output is written here as an expanding
-; zero-terminated string
-text_out_base = $6004
-
-bss_res text_out_temp
-zp_res text_out_addr,2
-
-init_text_out:
- ldx #0
-
- ; Put valid data first
- setb text_out_base,0
-
- lda #$80
- jsr set_final_result
-
- ; Now fill in signature that tells emulator there's
- ; useful data there
- setb text_out_base-3,$DE
- setb text_out_base-2,$B0
- setb text_out_base-1,$61
-
- ldx #>text_out_base
- stx text_out_addr+1
- setb text_out_addr,<text_out_base
- rts
-
-
-; Sets final result byte in memory
-set_final_result:
- sta final_result
- rts
-
-
-; Writes character to text output
-; In: A=Character to write
-; Preserved: A, X, Y
-write_text_out:
- sty text_out_temp
-
- ; Write new terminator FIRST, then new char before it,
- ; in case emulator looks at string in middle of this routine.
- ldy #1
- pha
- lda #0
- sta (text_out_addr),y
- dey
- pla
- sta (text_out_addr),y
-
- inc text_out_addr
- bne :+
- inc text_out_addr+1
-:
- ldy text_out_temp
- rts
View
126 test_roms/apu_mixer/source/common/vol_shell.inc
@@ -1,126 +0,0 @@
-; Shell for mixer tests
-
-CUSTOM_PLAY=1
-.include "shell.inc"
-
-.ifndef CUSTOM_TEXT
- text: .byte "2. Should be nearly silent.",0
-.endif
-
-main:
- jsr dmc_dac_to_127
- jsr make_triangle_zero
- jsr show_instructions
- jsr quiet_ppu
- jsr short_tone
- jsr test_main
- jsr short_tone
- jsr console_show
- rts
-
-
-dmc_dac_to_127:
- ldx #0
-: dey
- bne :-
- ldy #20
- stx $4011
- inx
- bpl :-
- rts
-
-
-; Runs triangle until its output is zero, avoiding its
-; attenuating effect on tests (at power, it starts with
-; its DAC at 15).
-make_triangle_zero:
-.ifndef USING_DEVCART
- setb $4015,0 ; off
- setb $4008,$04 ; lin ctr
- setb $400A,$FF ; period=256
- setb $400B,$08
- delay_msec 10 ; wait for lin ctr to load
- setb $4015,$04 ; on
- setb $400B,$08 ; start
- delay 256*16-12 ; allow 16 clocks
- setb $4015,0 ; off
-.endif
- rts
-
-
-; Prints instructions for test
-show_instructions:
- .ifdef USING_DEVCART
- rts
- .endif
-
- setw addr,filename
- jsr print_str_addr
- print_str " channel mixing test",{newline,newline}
-
- print_str "1. Should play short tone.",{newline,newline}
-
- setw addr,text
- jsr print_str_addr
- print_str {newline,newline}
-
- print_str "3. Should play short tone.",{newline,newline}
-
- print_str "Some clicking might occur between the two tones."
- print_str "Also, a faint tone might be audible through headphones."
- print_str newline,newline
-
- .ifndef BUILD_NSF
- delay_msec 1000
- delay_msec 1000
- delay_msec 1000