diff --git a/doc/notes.txt b/doc/notes.txt index 5ffa5f30..b5e62a8d 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -51,6 +51,7 @@ TODO: - Revert loads cached files? - Verilog compile spins forever? - how to revert included files? +- go to error in include files WEB WORKER FORMAT diff --git a/presets/nes/ex2.asm b/presets/nes/ex2.asm new file mode 100644 index 00000000..e8630c59 --- /dev/null +++ b/presets/nes/ex2.asm @@ -0,0 +1,141 @@ + + include "nesdefs.asm" + +;;;;; ZERO-PAGE VARIABLES + + seg.u Zeropage + org $0 + +ScrollPos byte ; used during NMI +Rand byte +Temp1 byte + +SpriteBuf equ $200 + + NES_HEADER 0,2,1,0 ; mapper 0, 2 PRGs, 1 CHR, vertical + +Start: + NES_INIT ; set up stack pointer, turn off PPU + jsr WaitSync + jsr WaitSync + jsr ClearRAM + jsr WaitSync ;wait for VSYNC + jsr SetPalette ;set colors + jsr FillVRAM ;set PPU RAM + jsr WaitSync ;wait for VSYNC (and PPU warmup) + jsr InitSprites + lda #0 + sta PPU_ADDR + sta PPU_ADDR ;PPU addr = 0 + sta PPU_SCROLL + sta PPU_SCROLL ;scroll = 0 + lda #$90 + sta PPU_CTRL ;enable NMI + lda #$1e + sta PPU_MASK ;enable rendering +.endless + jmp .endless ;endless loop + +InitSprites: subroutine + lda #1 + ldx #0 +.loop + sta SpriteBuf,x + jsr NextRandom + inx + bne .loop + rts + +MoveSprites: subroutine + lda #1 + ldx #0 +.loop + sta Temp1 + lda Temp1 + and #3 + clc + adc SpriteBuf,x + sta SpriteBuf,x + lda Temp1 + jsr NextRandom + inx + bne .loop + rts + +; set palette colors + +SetPalette: subroutine + ldy #$00 + lda #$3f + sta PPU_ADDR + sty PPU_ADDR + ldx #32 +.loop: + lda Palette,y + sta PPU_DATA + iny + dex + bne .loop + rts + + +;;;;; COMMON SUBROUTINES + + include "nesppu.asm" + +;;;;; INTERRUPT HANDLERS + +NMIHandler: +; save registers + pha ; save A +; load sprites + lda #$02 + sta PPU_OAM_DMA +; update scroll position (must be done after VRAM updates) + inc ScrollPos + lda ScrollPos + sta PPU_SCROLL + lda #0 + sta PPU_SCROLL +; TODO: write high bits to PPUCTRL + lda ScrollPos + and #0 + ora #$90 ; enable NMI + sta PPU_CTRL +; move sprites + jsr MoveSprites +; reload registers + pla ; reload A + rti + +;;;;; CONSTANT DATA + + align $100 +Palette: + hex 1f ;background + hex 09091900 ;bg0 + hex 09091900 ;bg1 + hex 09091900 ;bg2 + hex 09091900 ;bg3 + hex 14243400 ;sp0 + hex 15253500 ;sp1 + hex 16263600 ;sp2 + hex 17273700 ;sp3 + +;;;;; CPU VECTORS + + NES_VECTORS + +;;;;; TILE SETS + + org $10000 + REPEAT 64 + hex 003c6666766e663c007e181818381818 + hex 007e60300c06663c003c66061c06663c + hex 0006067f661e0e06003c6606067c607e + hex 003c66667c60663c00181818180c667e + hex 003c66663c66663c003c66063e66663c + hex 01010101010101010000000000000000 + hex ff000000000000000000000000000000 + hex 01020408102040800000000000000000 + REPEND diff --git a/presets/nes/nesdefs.asm b/presets/nes/nesdefs.asm new file mode 100644 index 00000000..f8a41b6e --- /dev/null +++ b/presets/nes/nesdefs.asm @@ -0,0 +1,64 @@ + + processor 6502 + +;;;;; CONSTANTS + +PPU_CTRL equ $2000 +PPU_MASK equ $2001 +PPU_STATUS equ $2002 +OAM_ADDR equ $2003 +OAM_DATA equ $2004 +PPU_SCROLL equ $2005 +PPU_ADDR equ $2006 +PPU_DATA equ $2007 +PPU_OAM_DMA equ $4014 +DMC_FREQ equ $4010 +APU_STATUS equ $4015 + + +;;;;; CARTRIDGE FILE HEADER + +NES_MIRR_HORIZ equ 0 +NES_MIRR_VERT equ 1 +NES_MIRR_QUAD equ 8 + + MAC NES_HEADER + seg Header + org $7ff0 +.NES_MAPPER SET {1} ;mapper number +.NES_PRG_BANKS SET {2} ;number of 16K PRG banks, change to 2 for NROM256 +.NES_CHR_BANKS SET {3} ;number of 8K CHR banks (0 = RAM) +.NES_MIRRORING SET {4} ;0 horizontal, 1 vertical, 8 four screen + byte $4e,$45,$53,$1a ; header + byte .NES_PRG_BANKS + byte .NES_CHR_BANKS + byte .NES_MIRRORING|(.NES_MAPPER<<4) + byte .NES_MAPPER&$f0 + byte 0,0,0,0,0,0,0,0 ; reserved, set to zero + seg Code + org $8000 + ENDM + +;;;;; NES_INIT SETUP MACRO (place at start) + + MAC NES_INIT + sei ;disable IRQs + cld ;decimal mode not supported + ldx #$ff + txs ;set up stack pointer + inx ;increment X to 0 + stx PPU_MASK ;disable rendering + stx DMC_FREQ ;disable DMC interrupts + stx PPU_CTRL ;disable NMI interrupts + bit PPU_STATUS ;clear VBL flag + ENDM + +;;;;; NES_VECTORS - CPU vectors at end of address space + + MAC NES_VECTORS + seg Vectors + org $fffa + .word NMIHandler ;$fffa vblank nmi + .word Start ;$fffc reset + .word NMIHandler ;$fffe irq / brk (not used) + ENDM diff --git a/presets/nes/nesppu.asm b/presets/nes/nesppu.asm new file mode 100644 index 00000000..65e5a3ad --- /dev/null +++ b/presets/nes/nesppu.asm @@ -0,0 +1,59 @@ +;;;;; SUBROUTINES + +ClearRAM: subroutine + lda #0 + tax +.clearRAM + sta $0,x + cpx #$fe ; don't clear last 2 bytes of stack + bcs .skipStack + sta $100,x +.skipStack + ; skip $200-$2FF, used for OAM display list + sta $300,x + sta $400,x + sta $500,x + sta $600,x + sta $700,x + inx + bne .clearRAM + rts + +; fill video RAM +FillVRAM: subroutine + txa + ldy #$20 + sty PPU_ADDR + sta PPU_ADDR + ldy #$10 +.loop: + sta PPU_DATA + adc #7 + inx + bne .loop + dey + bne .loop + rts + +; wait for VSYNC to start +WaitSync: + bit PPU_STATUS + bpl WaitSync + rts + +;;;;; RANDOM NUMBERS + +NextRandom subroutine + lsr + bcc .NoEor + eor #$d4 +.NoEor: + rts +; Get previous random value +PrevRandom subroutine + asl + bcc .NoEor + eor #$a9 +.NoEor: + rts + diff --git a/src/platform/nes.js b/src/platform/nes.js index 548537c9..298e58b8 100644 --- a/src/platform/nes.js +++ b/src/platform/nes.js @@ -1,8 +1,9 @@ "use strict"; var JSNES_PRESETS = [ - {id:'ex0.asm', name:'Initialization (ASM)'}, - {id:'ex1.asm', name:'Scrolling Demo (ASM)'}, + {id:'ex0.asm', name:'Initialization'}, + {id:'ex1.asm', name:'Scrolling Demo'}, + {id:'ex2.asm', name:'Sprite Demo'}, // {id:'hello.c', name:'C: Hello PPU'}, // {id:'conio.c', name:'C: Hello Console I/O'}, {id:'siegegame.c', name:'Siege Game (C)'}, diff --git a/src/project.ts b/src/project.ts index 9e5a0a26..946d8971 100644 --- a/src/project.ts +++ b/src/project.ts @@ -52,8 +52,7 @@ export class CodeProject { } } - // TODO: support link-time and compile-time (include) dependencies - parseFileDependencies(text:string):string[] { + parseIncludeDependencies(text:string):string[] { var files = []; if (this.platform_id == 'verilog') { var re = /^\s*(`include|[.]include)\s+"(.+?)"/gm; @@ -63,6 +62,21 @@ export class CodeProject { //files.push('local/'+m[2]); // TODO: shows up 2x in interface } } else { + // for .asm -- [.]include "file" + var re2 = /^\s+([.]?include)\s+"(.+?)"/gm; + while (m = re2.exec(text)) { + files.push(m[2]); + } + } + return files; + } + + parseLinkDependencies(text:string):string[] { + var files = []; + if (this.platform_id == 'verilog') { + // + } else { + // for .c -- //#link "file" (or ;link or #link) var re = /^\s*([;#]|[/][/][#])link\s+"(.+?)"/gm; var m; while (m = re.exec(text)) { @@ -73,8 +87,15 @@ export class CodeProject { } loadFileDependencies(text:string, callback:LoadFilesCallback) { - var paths = this.parseFileDependencies(text); - this.loadFiles(paths, callback); + var includes = this.parseIncludeDependencies(text); + var linkfiles = this.parseLinkDependencies(text); + var allfiles = includes.concat(linkfiles); + this.loadFiles(allfiles, (err:string, result?:Dependency[]) => { + if (result) + for (var dep of result) + dep.link = linkfiles.indexOf(dep.filename) >= 0; + callback(err, result); + }); } okToSend():boolean { @@ -96,11 +117,17 @@ export class CodeProject { // TODO: add preproc directive for __MAINFILE__ var mainfilename = getFilenameForPath(this.mainpath); var maintext = this.getFile(this.mainpath); + var files = [mainfilename]; msg.updates.push({path:mainfilename, data:maintext}); - msg.buildsteps.push({path:mainfilename, platform:this.platform_id, tool:this.platform.getToolForFilename(this.mainpath), mainfile:true}); - for (var i=0; i