Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
veremenko-y committed Feb 12, 2019
0 parents commit 4901241
Show file tree
Hide file tree
Showing 21 changed files with 1,942 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.dbg
*.nes
*.o
game.map
src/dialogues/*_msg.inc
src/levels/*_data.inc
src/levels/levels_*.inc
src/levels/*.nam
10 changes: 10 additions & 0 deletions .vscode/keybindings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

[{
"key": "ctrl+r",
"command": "workbench.action.tasks.runTask",
"when": "run build"
},{
"key": "ctrl+b",
"command": "workbench.action.tasks.runTask",
"when": "run debug"
}]
15 changes: 15 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"editor.detectIndentation": false,
"editor.tabSize": 4,
"AllAutocomplete.languageSpecialCharacters": {
"inc": "^[\\.#]",
"asm": "^[\\.#]"
},
"AllAutocomplete.languageWhitespace": {
"ca65": "[^\\w_\\u0080-\\uFFFF]+"
},
"AllAutocomplete.wordListFiles": [
"nes.inc"
],
"editor.acceptSuggestionOnEnter": "smart"
}
49 changes: 49 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "debug",
"type": "shell",
"command": "make run"
},
{
"label": "build",
"type": "shell",
"command": "make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [{
"owner": "cc65",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^(.*)\\((\\d+)\\):\\s+(Warning|Error):\\s+(.*)$",
"file": 1,
"line": 2,
"severity": 3,
"message": 4
}
}, {
"owner": "cc65",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^(ld65.exe):\\s+(Warning|Error):\\s+(.*)$",
"file": 1,
"line": 1,
"severity": 2,
"message": 3
}
}],
"presentation": {
"echo": true,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": true
}
}
]
}
339 changes: 339 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
CX65 = ../cc65/bin
CC65 = $(CX65)/cc65.exe
CA65 = $(CX65)/ca65.exe
LD65 = $(CX65)/ld65.exe
EMU = ../tools/mesen/mesen.exe
LP = lprun

all: game.nes

clean:
del *.nes *.dbg
del src\*.o

run:
$(EMU) game.nes

%.o: src/%.asm
@ $(CA65) -g $<

game.nes: header.o boot.o main.o ppu.o lib.o bf.o
@ $(LD65) --dbgfile game.dbg -m game.map -C nes.cfg -o game.nes src/boot.o src/main.o src/header.o src/ppu.o src/lib.o src/bf.o

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# NES Brainfuck

Brainfuck VM for NES. Uses ca65 macroses to generate binary for supplied Brainfuck code. Read operator is not supported.
1 change: 1 addition & 0 deletions assets/palette.pal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*'8881'  )
Binary file added assets/tiles.chr
Binary file not shown.
21 changes: 21 additions & 0 deletions nes.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
SYMBOLS {
__STACKSIZE__: type = weak, value = $0300; # 3 pages stack
}
MEMORY {
ZP: file = "", start = $0000, size = $00FF, type = rw, define = yes;
HEADER: file = %O, start = $0000, size = $0010, fill = yes;
PRG: file = %O, start = $8000, size = $8000, fill = yes, define = yes;
CHR: file = %O, start = $0000, size = $2000, fill = yes, define = yes;
SPRITE_RAM: file = "", start = $0200, size = $0100, define = yes;
RAM: file = "", start = $0300, size = $0500, define = yes;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
HEADER: load = HEADER, type = ro;
CODE: load = PRG, type = ro, define = yes;
RODATA: load = PRG, type = ro, define = yes;
VECTORS: load = PRG, type = rw, start = $fffa;
OAM: load = SPRITE_RAM type = rw;
CHR: load = CHR type = ro;
BSS: load = RAM, type = bss, define = yes;
}
61 changes: 61 additions & 0 deletions src/bf.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.include "lib.inc"
.include "ppu.inc"
.include "nes.inc"
.include "bf.inc"

.segment "BSS"
BF_ram: .res 1024
.segment "ZEROPAGE"
BF_ptr: .res 2
BF_line: .res 1

.segment "CODE"
.proc BF_incp
inc BF_ptr+0
bne :+
inc BF_ptr+1
:
rts
.endproc
.proc BF_decp
dec BF_ptr+0
bne :+
dec BF_ptr+1
:
rts
.endproc
.proc BF_inc
ldy #0
lda (BF_ptr),y
clc
adc #1
sta (BF_ptr),y
rts
.endproc
.proc BF_dec
ldy #0
lda (BF_ptr),y
sec
sbc #1
sta (BF_ptr),y
rts
.endproc
.proc BF_print
ldy #0
lda (BF_ptr),y
cmp #$0A
bne :+
lda BF_line
add #1
sta BF_line
call ppu_SetAddr, #>PPU_ADDR_NAMETABLE1, #1, BF_line
jmp :++
:
sta PPU_DATA
:
rts
.endproc
.proc BF_read
rts
.endproc

72 changes: 72 additions & 0 deletions src/bf.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.ifndef BF_INC
.define BF_INC

.globalzp BF_ptr, BF_line
.global BF_ram
.global BF_incp
.global BF_decp
.global BF_inc
.global BF_dec
.global BF_print
.global BF_read

BF_MAX_SOURCE_LENGTH = 1024

bflabel .set 0
bfstack .set 0
.macro BF_compile src
lda #<BF_ram
sta BF_ptr+0
lda #>BF_ram
sta BF_ptr+1
lda #3
sta BF_line
m_ppu_BeginWrite
call ppu_FillNameTable, #>PPU_ADDR_NAMETABLE1, #$20, #0
call ppu_SetAddr, #>PPU_ADDR_NAMETABLE1, #1, BF_line
.if .strlen(src) > BF_MAX_SOURCE_LENGTH
.error .sprintf("Brainfuck source is too long. Max ", BF_MAX_SOURCE_LENGTH)
.endif
.repeat BF_MAX_SOURCE_LENGTH, i
.if i < .strlen(src)
.if .strat(src, i) = '>'
jsr BF_incp
.endif
.if .strat(src, i) = '<'
jsr BF_decp
.endif
.if .strat(src, i) = '+'
jsr BF_inc
.endif
.if .strat(src, i) = '-'
jsr BF_dec
.endif
.if .strat(src, i) = '.'
jsr BF_print
.endif
.if .strat(src, i) = ','
jsr BF_read
.endif
.if .strat(src, i) = '['
.ident(.concat("BF_LABEL", .sprintf("%d", bflabel))):
ldy #0
lda (BF_ptr),y
bne :+
jmp .ident(.concat("BF_LABEL_END", .sprintf("%d", bflabel)))
:
; put label onto stack
bfstack .set bfstack + 1
.ident(.concat("bfstack", .sprintf("%d", bfstack))) .set bflabel
bflabel .set bflabel + 1
.endif
.if .strat(src, i) = ']'
jmp .ident(.concat("BF_LABEL", .sprintf("%d", .ident(.concat("bfstack", .sprintf("%d", bfstack))))))
.ident(.concat("BF_LABEL_END", .sprintf("%d", .ident(.concat("bfstack", .sprintf("%d", bfstack)))))):
bfstack .set bfstack - 1
.endif
.endif
.endrep
rts
.endmacro

.endif
104 changes: 104 additions & 0 deletions src/boot.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
.include "nes.inc"
.include "ppu.inc"

.import main

.segment "CODE"
reset:
sei ; ignore IRQs
cld ; disable decimal mode
ldx #APU_FRAMECT_IRQ_DISABLE
stx APU_FRAMECT ; disable APU frame IRQ
ldx #$ff
txs ; Set up stack
inx ; now X = 0
stx PPU_CTRL ; disable NMI
stx PPU_MASK ; disable rendering
stx APU_MODCTRL ; disable DMC IRQs

; Optional (omitted):
; Set up mapper and jmp to further init code here.

; If the user presses Reset during vblank, the PPU may reset
; with the vblank flag still true. This has about a 1 in 13
; chance of happening on NTSC or 2 in 9 on PAL. Clear the
; flag now so the @vblankwait1 loop sees an actual vblank.
bit PPU_STATUS

; First of two waits for vertical blank to make sure that the
; PPU has stabilized
:
bit PPU_STATUS
bpl :-

; Clear ram
txa
:
sta $000,x
sta $100,x
sta $300,x
sta $400,x
sta $500,x
sta $600,x
sta $700,x
inx
bne :-
; Clear OAM region
lda #$ff
:
sta $200,x
inx
bne :-

:
bit PPU_STATUS
bpl :-

; Enable NMI in order for ppu_On and ppu_Off to work
lda PPU_STATUS ; Prevent immediate NMIs
lda #PPU_CTRL_NMI_ON
sta PPU_CTRL

lda #0
jmp main

; -----------------------------------------------------------------------------
; V-Blank interupt handler
nmi:
pushseg
; Write to OAM DMA
lda ppu_needOam
beq @oamEnd
mova ppu_needOam, #0 ; reset OAM flag
lda #<ppu_oam
sta PPU_SPR_ADDR
lda #>ppu_oam
sta APU_SPR_DMA
@oamEnd:

lda ppu_hasBuffer
beq @bufferEnd
jsr ppu_OutputBuffer
@bufferEnd:
; Fix scroll
mova PPU_SCROLL, ppu_scrollx
mova PPU_SCROLL, ppu_scrolly

@end:
m_ppu_SetNmiDone
popseg
rti

irq:
rti

.proc lib_SwitchBank
and #$0F
sta $8000
rts
.endproc

.segment "VECTORS"
.word nmi
.word reset
.word irq
13 changes: 13 additions & 0 deletions src/header.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.segment "HEADER"
; iNES header
; see http://wiki.nesdev.com/w/index.php/INES
.byte $4e, $45, $53, $1a ; "NES" followed by MS-DOS EOF
.byte $02 ; size of PRG ROM in 16 KiB units
.byte $01 ; size of CHR ROM in 8 KiB units
.byte $30 ; horizontal mirroring, mapper 003 (CNROM)
.byte $00 ; mapper 003 (CNROM)

.byte $00 ; size of PRG RAM in 8 KiB units
.byte $00 ; NTSC
.byte $00 ; unused
.res 5, $00
Loading

0 comments on commit 4901241

Please sign in to comment.