Share My Creation B4J NES Emulator Project

As I already mentioned 'ages ago' in the 6502 emu thread, I’ve been tinkering away at writing an NES emulator in B4J.
After the first experiments — which some of you bravely tested as an alpha version — I’ve now made a big leap forward🚀

I completely rewrote the APU, PPU, and the mapper code. With these changes, the emulator now finally has proper access to mapper classes.

At the moment, the following mappers are up and running (which definitely does not mean they’re bug-free 😉):

MAPPER000
MAPPER001
MAPPER002
MAPPER003
MAPPER004
MAPPER005
MAPPER007
MAPPER009
MAPPER010
MAPPER024
MAPPER062
MAPPER221
MAPPER227

With this lineup, it should be possible to play most ROMs — at least until the next bug shows up 😄 ( I know a few....)
Mapper descriptions can be found here: https://www.nesdev.org/wiki/Mapper



Default key mappings (Controller 1)
S = Select
F = A
D = B
Return = Start
Up = Up
Down = Down
Left = Left
Right = Right

' Controller 2
N = Select
J = A
H = B
M = Start
I = Up
K = Down
U = Left
O = Right


As always ....

.... have Fun

p.s. I will share the code when I have an official RC
 
Last edited:

madru

Active Member
Licensed User
Longtime User

B4J NES Emulator Project



B4JNES - Complete Documentation and Sourcecode



Overview​

The B4J NES Emulator is a comprehensive Nintendo Entertainment System (NES) emulator written in B4J (Basic for Java). It provides accurate emulation of the NES hardware including the CPU, PPU, APU, and various memory mappers.

Features​

  • Complete 6502 CPU Emulation: All 151 official opcodes plus 105 undocumented opcodes
  • Accurate PPU Emulation: Cycle-accurate rendering with proper sprite evaluation
  • APU Sound Support: All 5 audio channels (2 pulse, triangle, noise, DMC)
  • 25+ Memory Mappers: Support for most common NES games
  • Game Genie Support: Built-in cheat code system
  • Save States: Save and load game progress
  • Debug Tools: Sprite viewer, audio visualizer, ROM analyzer

System Requirements​

  • Java Runtime Environment 8 or higher
  • B4J IDE (for development)
  • Minimum 512MB RAM recommended

License​

This software is released under the GNU General Public License v3.0 (GPL-3.0).
Copyright (C) 2026 B4J NES Emulator Project

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

GPL-3.0 Compliance Notes​

All source files include the standard GPL-3.0 header. When distributing modified versions:
  1. Include the complete source code
  2. Maintain all copyright notices
  3. Document any modifications
  4. Use the same GPL-3.0 license

Architecture​

Component Diagram​

1769085925614.png

Data Flow​

  1. ROM Loading: CARTRIDGE parses iNES/NES 2.0 headers and loads PRG/CHR data
  2. Mapper Selection: MAPPERBASE selects and initializes appropriate mapper
  3. Frame Execution: NESEMULATOR runs CPU instructions and syncs PPU
  4. Rendering: PPU generates pixel data, output to display buffer
  5. Audio: APU generates samples, sent to audio output

Core Components​

NESEMULATOR.bas​

Purpose: Main emulation controller that coordinates all components.
Key Functions:
FunctionDescription
Initialize()Initializes all emulator components
LoadROM(fileName)Loads a NES ROM file
ExecFrame()Executes one complete video frame
ResetSoft()Soft reset (preserves RAM)
ResetHard()Hard reset (clears all state)
SaveStateToFile()Saves emulation state
LoadStateFromFile()Restores emulation state
Timing Constants:
  • CPU_CYCLES_PER_FRAME: 29,780 (NTSC)
  • PAL_CPU_CYCLES_PER_FRAME: 33,248 (PAL)
  • PPU_CYCLES_PER_CPU: 3

CPU6502.bas​

Purpose: Emulates the MOS 6502 processor used in the NES (specifically the Ricoh 2A03).

Registers:
RegisterSizeDescription
A8-bitAccumulator
X8-bitX Index Register
Y8-bitY Index Register
SP8-bitStack Pointer ($01xx)
PC16-bitProgram Counter
P8-bitProcessor Status

Status Flags (P Register):
BitFlagDescription
7NNegative
6VOverflow
5-Unused (always 1)
4BBreak
3DDecimal Mode
2IInterrupt Disable
1ZZero
0CCarry

Addressing Modes:
  1. Implied: No operand (e.g., NOP, RTS)
  2. Accumulator: Operates on A (e.g., ASL A)
  3. Immediate: #$nn (e.g., LDA #$10)
  4. Zero Page: $nn (e.g., LDA $10)
  5. Zero Page,X: $nn,X (e.g., LDA $10,X)
  6. Zero Page,Y: $nn,Y (e.g., LDX $10,Y)
  7. Absolute: $nnnn (e.g., LDA $1234)
  8. Absolute,X: $nnnn,X (e.g., LDA $1234,X)
  9. Absolute,Y: $nnnn,Y (e.g., LDA $1234,Y)
  10. Indirect: ($nnnn) (JMP only)
  11. Indexed Indirect: ($nn,X) (e.g., LDA ($10,X))
  12. Indirect Indexed: ($nn),Y (e.g., LDA ($10),Y)
Interrupt Vectors:
AddressType
FFFA−FFFA−FFFBNMI
FFFC−FFFC−FFFDRESET
FFFE−FFFE−FFFFIRQ/BRK

PPU.bas​

Purpose: Emulates the Picture Processing Unit (2C02).
Resolution: 256x240 pixels, 64 colors

Key Registers:
AddressNameDescription
$2000PPUCTRLControl register
$2001PPUMASKMask register
$2002PPUSTATUSStatus register
$2003OAMADDROAM address
$2004OAMDATAOAM data
$2005PPUSCROLLScroll position
$2006PPUADDRVRAM address
$2007PPUDATAVRAM data

Timing:
  • 341 PPU cycles per scanline
  • 262 scanlines per frame (NTSC)
  • 312 scanlines per frame (PAL)
Memory Layout:
RangeSizeDescription
$0000-$0FFF4KBPattern Table 0
$1000-$1FFF4KBPattern Table 1
$2000-$23FF1KBNametable 0
$2400-$27FF1KBNametable 1
$2800-$2BFF1KBNametable 2
$2C00-$2FFF1KBNametable 3
$3F00-$3F1F32BPalettes

APU.bas​

Purpose: Emulates the Audio Processing Unit.

Channels:
ChannelTypeDescription
Pulse 1Square WaveDuty cycle, sweep, envelope
Pulse 2Square WaveDuty cycle, sweep, envelope
TriangleTriangle WaveLinear counter
NoiseLFSR NoiseMode select, envelope
DMCDelta PCMSample playback

Registers ($4000-$4017):
RangeChannel
$4000-$4003Pulse 1
$4004-$4007Pulse 2
$4008-$400BTriangle
$400C-$400FNoise
$4010-$4013DMC
$4015Status/Control
$4017Frame Counter

MEMORY.bas​

Purpose: Memory bus controller handling all CPU memory access.

Memory Map:
RangeSizeDescription
$0000-$07FF2KBInternal RAM
$0800-$1FFF-RAM Mirrors
$2000-$20078BPPU Registers
$2008-$3FFF-PPU Register Mirrors
$4000-$4017-APU/IO Registers
$4018-$401F-Disabled APU/IO
$4020-$5FFF-Expansion ROM
$6000-$7FFF8KBBattery-backed RAM
8000−8000−BFFF16KBPRG ROM Bank 0
C000−C000−FFFF16KBPRG ROM Bank 1

CARTRIDGE.bas​

Purpose: ROM loading and parsing.
Supported Formats:
  • iNES 1.0 (.nes)
  • NES 2.0 (.nes)
Header Structure (16 bytes):
OffsetSizeDescription
0-34B“NES” + $1A
41BPRG ROM size (16KB units)
51BCHR ROM size (8KB units)
61BFlags 6
71BFlags 7
8-158BExtended flags

Mirroring Modes:
  • 0: Horizontal
  • 1: Vertical
  • 2: Four-screen
  • 3: Single-screen (lower)
  • 4: Single-screen (upper)

Memory Mapping​

Bank Switching​

The emulator uses 1KB bank granularity for both PRG and CHR:
PRG Banks: 32 x 1KB banks covering 8000−8000−FFFF
CHR Banks: 8 x 1KB banks covering $0000-$1FFF

Bank Swap Functions​

' PRG bank swap
mem.PRGswap(banknum, newbank, banksize)

' CHR bank swap
mem.CHRswap(banknum, newbank, banksize)


Supported Mappers​

MapperNameDescription
0NROMNo bank switching
1MMC1Nintendo’s first mapper
2UxROMSimple PRG switching
3CNROMSimple CHR switching
4MMC3Most popular mapper
5MMC5Advanced mapper
7AxROMSingle-screen mirroring
9MMC2Punch-Out!! mapper
10MMC4Fire Emblem mapper
11Color DreamsUnlicensed
22VRC2aKonami
23VRC2b/VRC4Konami
24VRC6Konami with audio
25VRC4b/VRC4dKonami
28Action 53Modern homebrew
34BNROM/NINASimple PRG
62MulticartMulti-game
66GxROMSimple
69Sunsoft FME-7With audio
71CamericaCodemasters
83Yoko/ConyPirate
118TxSROMMMC3 variant
221NTDECMulticart
227MulticartMulti-game

API Reference​

NESEMULATOR Class​

Initialize()​

Initializes all emulator components. Must be called before loading a ROM.

LoadROM(fileName As String) As Boolean​

Loads a NES ROM file.
  • Parameters: fileName - Full path to .nes file
  • Returns: True if successful

ExecFrame()​

Executes one complete video frame (~29,780 CPU cycles).

ResetSoft()​

Performs a soft reset, preserving RAM contents.

ResetHard()​

Performs a hard reset, clearing all memory.

Start() / Stop()​

Controls emulation execution state.

KeyPressed(keyName As String) / KeyReleased(keyName As String)​

Handles controller input.

CPU6502 Class​

Initialize(m As Object)​

Initializes CPU with memory interface.

Reset()​

Resets CPU to power-on state.

Step() As Int​

Executes one instruction, returns cycles consumed.

DoNMI()​

Triggers Non-Maskable Interrupt.

DoIRQ()​

Triggers Interrupt Request (if enabled).

PPU Class​

Initialize(memRef, mapperRef, cartRef, cpuRef)​

Initializes PPU with component references.

Tick() As Boolean​

Executes one PPU cycle. Returns True when frame complete.

ReadRegister(addr As Int) As Int​

Reads PPU register ($2000-$2007).

WriteRegister(addr As Int, value As Int)​

Writes PPU register.

Building and Running​

Prerequisites​

  1. Install B4J IDE from https://www.b4x.com/b4j.html
  2. Install Java JDK 8 or higher

Build Steps​

  1. Open NES.b4j in B4J IDE
  2. Configure libraries path in IDE settings
  3. Click Build/Run or press F5

Default Controls​

Controller 1:
ButtonKey
AF
BD
SelectS
StartEnter
D-PadArrow Keys

Controller 2:
ButtonKey
AJ
BH
SelectN
StartM
D-PadI/K/U/O

System Keys:
FunctionKey
Pause/UnpauseEscape
HUDF1
Record Audio StartF2
Recording StopF3
Screenshot to ClipboardF12

File List​

FileDescription
APU.basAudio Processing Unit - generates NES audio
AudioViewer.basDebug audio visualizer
CARTRIDGE.basROM loader and cartridge management
CPU6502.bas6502 CPU emulation core
CRC32.basCRC32 checksum calculator
GAMEGENIE.basGame Genie cheat code engine
GameGenieDialog.basGame Genie code entry dialog
INPUTHANDLER.basController input handler
InputConfigDialog.basController configuration GUI
MAPPER000.basMapper 0 - NROM (no mapper)
MAPPER001.basMapper 1 - MMC1 (SxROM)
MAPPER002.basMapper 2 - UxROM
MAPPER003.basMapper 3 - CNROM
MAPPER004.basMapper 4 - MMC3 (TxROM)
MAPPER005.basMapper 5 - MMC5 (ExROM)
MAPPER007.basMapper 7 - AxROM
MAPPER009.basMapper 9 - MMC2 (PxROM)
MAPPER010.basMapper 10 - MMC4 (FxROM)
MAPPER011.basMapper 11 - Color Dreams
MAPPER022.basMapper 22 - VRC2a
MAPPER023.basMapper 23 - VRC2b/VRC4
MAPPER024.basMapper 24 - VRC6a
MAPPER025.basMapper 25 - VRC4b/VRC4d
MAPPER028.basMapper 28 - Action 53
MAPPER034.basMapper 34 - BNROM/NINA-001
MAPPER062.basMapper 62 - Super 700-in-1
MAPPER066.basMapper 66 - GxROM
MAPPER069.basMapper 69 - FME-7/Sunsoft 5B
MAPPER071.basMapper 71 - Camerica/Codemasters
MAPPER083.basMapper 83 - Cony/Yoko
MAPPER118.basMapper 118 - TxSROM (MMC3 variant)
MAPPER221.basMapper 221 - N625092
MAPPER227.basMapper 227 - 1200-in-1
MAPPERBASE.basBase mapper class and mapper factory
MEMORY.basMemory bus controller
NESEMULATOR.basMain emulator controller
PPU.basPicture Processing Unit - graphics rendering
ROMAnalyzer.basROM information analyzer
SAVESTATE.basSave state management
SpriteViewer.basDebug sprite viewer

Changelog​


Version 1.1.0​

  • Added pause/unpause functionality (ESC key)
  • Added screenshot to clipboard (F12 key)
  • Added controller configuration dialog (InputConfigDialog)
  • Configurable key bindings with save/load support
  • Code refactoring with getter/setter encapsulation
  • Input validation and bounds checking throughout

Version 1.0.0​

  • Initial release with GPL-3.0 license
  • Support for 25+ mappers
  • Full CPU, PPU, and APU emulation
  • Game Genie support
  • Save state support
  • Debug tools

Documentation for B4J NES Emulator Project
Licensed under GPL-3.0
 

Attachments

  • NES.zip
    139.8 KB · Views: 4
Top