mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-04-02 07:29:52 +00:00
add path to (some) error msgs; fixed code analysis bugs (?)
This commit is contained in:
parent
662f8a057d
commit
a9bd845800
427
presets/nes/road.asm
Normal file
427
presets/nes/road.asm
Normal file
@ -0,0 +1,427 @@
|
||||
|
||||
include "nesdefs.asm"
|
||||
|
||||
;;;;; ZERO-PAGE VARIABLES
|
||||
|
||||
seg.u ZEROPAGE
|
||||
org $0
|
||||
|
||||
TrackFrac .byte ; fractional position along track
|
||||
Speed .byte ; speed of car
|
||||
TimeOfDay .word ; 16-bit time of day counter
|
||||
; Variables for preprocessing step
|
||||
XPos .word ; 16-bit X position
|
||||
XVel .word ; 16-bit X velocity
|
||||
TPos .word ; 16-bit track position
|
||||
TrackLookahead .byte ; current fractional track increment
|
||||
; Variables for track generation
|
||||
Random .byte ; random counter
|
||||
GenTarget .byte ; target of current curve
|
||||
GenDelta .byte ; curve increment
|
||||
GenCur .byte ; current curve value
|
||||
|
||||
ZOfs .byte ; counter to draw striped center line
|
||||
Weather .byte ; bitmask for weather
|
||||
Heading .word ; sky scroll pos.
|
||||
|
||||
XCenter = 128
|
||||
NumRoadSegments = 28
|
||||
|
||||
; Preprocessing result: X positions for all track segments
|
||||
RoadX0 ds NumRoadSegments
|
||||
|
||||
; Generated track curve data
|
||||
TrackLen equ 5
|
||||
TrackData ds TrackLen
|
||||
|
||||
InitialSpeed equ 10 ; starting speed
|
||||
|
||||
;;;;; OTHER VARIABLES
|
||||
|
||||
seg.u RAM
|
||||
org $300
|
||||
|
||||
;;;;; NES CARTRIDGE HEADER
|
||||
|
||||
NES_HEADER 0,2,1,0 ; mapper 0, 2 PRGs, 1 CHR, horiz. mirror
|
||||
|
||||
;;;;; START OF CODE
|
||||
|
||||
Start:
|
||||
NES_INIT ; set up stack pointer, turn off PPU
|
||||
jsr WaitSync ; wait for VSYNC
|
||||
jsr ClearRAM ; clear RAM
|
||||
jsr WaitSync ; wait for VSYNC (and PPU warmup)
|
||||
|
||||
jsr SetPalette ; set palette colors
|
||||
jsr FillVRAM ; set PPU video RAM
|
||||
|
||||
jsr RoadSetup
|
||||
|
||||
lda #0
|
||||
sta PPU_ADDR
|
||||
sta PPU_ADDR ; PPU addr = $0000
|
||||
sta PPU_SCROLL
|
||||
sta PPU_SCROLL ; scroll = $0000
|
||||
lda #CTRL_NMI
|
||||
sta PPU_CTRL ; enable NMI
|
||||
lda #MASK_BG|MASK_SPR
|
||||
sta PPU_MASK ; enable rendering
|
||||
|
||||
.endless
|
||||
jmp .endless ; endless loop
|
||||
|
||||
;;;;; ROAD SUBS
|
||||
|
||||
RoadSetup: subroutine
|
||||
lda #1
|
||||
sta Random
|
||||
lda #InitialSpeed
|
||||
sta Speed
|
||||
lda #0
|
||||
sta TimeOfDay+1
|
||||
lda #0
|
||||
sta Weather
|
||||
rts
|
||||
|
||||
RoadPreSetup: subroutine
|
||||
; Set up some values for road curve computation,
|
||||
; since we have some scanline left over.
|
||||
lda #0
|
||||
sta XVel
|
||||
sta XVel+1
|
||||
sta XPos
|
||||
sta XPos+1
|
||||
lda TrackFrac
|
||||
sta TPos
|
||||
lda #0
|
||||
sta TPos+1
|
||||
lda #10 ; initial lookahead
|
||||
sta TrackLookahead
|
||||
rts
|
||||
|
||||
RoadPostFrame: subroutine
|
||||
; Advance position on track
|
||||
; TrackFrac += Speed
|
||||
lda TrackFrac
|
||||
clc
|
||||
adc Speed
|
||||
sta TrackFrac
|
||||
bcc .NoGenTrack ; addition overflowed?
|
||||
jsr GenTrack ; yes, generate new track segment
|
||||
.NoGenTrack
|
||||
; TimeOfDay += 1
|
||||
inc TimeOfDay
|
||||
bne .NoTODInc
|
||||
inc TimeOfDay+1
|
||||
lda TimeOfDay+1
|
||||
; See if it's nighttime yet, and if the stars come out
|
||||
clc
|
||||
adc #8
|
||||
and #$3f
|
||||
cmp #$35
|
||||
ror
|
||||
sta Weather
|
||||
.NoTODInc
|
||||
lda Heading
|
||||
sec
|
||||
sbc XPos+1
|
||||
sta Heading
|
||||
bit XPos+1
|
||||
bmi .NegHeading
|
||||
lda Heading+1
|
||||
sbc #0
|
||||
sta Heading+1
|
||||
rts
|
||||
.NegHeading
|
||||
lda Heading+1
|
||||
sbc #$ff
|
||||
sta Heading+1
|
||||
rts
|
||||
|
||||
; Compute road curve from bottom of screen to horizon.
|
||||
PreprocessCurve subroutine
|
||||
ldx #NumRoadSegments-1
|
||||
.CurveLoop
|
||||
; Modify X position
|
||||
; XPos += XVel (16 bit add)
|
||||
lda XPos
|
||||
clc
|
||||
adc XVel
|
||||
sta XPos
|
||||
lda XPos+1
|
||||
adc XVel+1
|
||||
sta XPos+1
|
||||
sta RoadX0,x ; store in RoadX0 array
|
||||
; Modify X velocity (slope)
|
||||
; XVel += TrackData[TPos]
|
||||
ldy TPos+1
|
||||
lda TrackData,y
|
||||
clc ; clear carry for ADC
|
||||
bmi .CurveLeft ; track slope negative?
|
||||
adc XVel
|
||||
sta XVel
|
||||
lda XVel+1
|
||||
adc #0 ; carry +1
|
||||
jmp .NoCurveLeft
|
||||
.CurveLeft
|
||||
adc XVel
|
||||
sta XVel
|
||||
lda XVel+1
|
||||
sbc #0 ; carry -1
|
||||
nop ; make the branch timings are the same
|
||||
.NoCurveLeft
|
||||
sta XVel+1
|
||||
; Advance TPos (TrackData index)
|
||||
; TPos += TrackLookahead
|
||||
lda TPos
|
||||
clc
|
||||
adc TrackLookahead
|
||||
sta TPos
|
||||
lda TPos+1
|
||||
adc #0
|
||||
sta TPos+1
|
||||
; Go to next segment
|
||||
inc TrackLookahead ; see further along track
|
||||
dex
|
||||
bpl .CurveLoop
|
||||
rts
|
||||
|
||||
; Generate next track byte
|
||||
GenTrack subroutine
|
||||
; Shift the existing track data one byte up
|
||||
; (a[i] = a[i+1])
|
||||
ldx #0
|
||||
.ShiftTrackLoop
|
||||
lda TrackData+1,x
|
||||
sta TrackData,x
|
||||
inx
|
||||
cpx #TrackLen-1
|
||||
bne .ShiftTrackLoop
|
||||
; Modify our current track value and
|
||||
; see if it intersects the target value
|
||||
lda GenCur
|
||||
clc
|
||||
adc GenDelta
|
||||
cmp GenTarget
|
||||
beq .ChangeTarget ; target == cur?
|
||||
bit GenTarget ; we need the sign flag
|
||||
bmi .TargetNeg ; target<0?
|
||||
bcs .ChangeTarget ; target>=0 && cur>=target?
|
||||
bcc .NoChangeTarget ; branch always taken
|
||||
.TargetNeg
|
||||
bcs .NoChangeTarget ; target<0 && cur<target?
|
||||
; Generate a new target value and increment value,
|
||||
; and make sure the increment value is positive if
|
||||
; the target is above the current value, and negative
|
||||
; otherwise
|
||||
.ChangeTarget
|
||||
lda Random
|
||||
jsr NextRandom ; get a random value
|
||||
sta Random
|
||||
and #$3f ; range 0..63
|
||||
sec
|
||||
sbc #$1f ; range -31..32
|
||||
sta GenTarget ; -> target
|
||||
cmp GenCur
|
||||
bmi .TargetBelow ; current > target?
|
||||
lda Random
|
||||
jsr NextRandom ; get a random value
|
||||
sta Random
|
||||
and #$f ; mask to 0..15
|
||||
jmp .TargetAbove
|
||||
.TargetBelow
|
||||
lda Random
|
||||
jsr NextRandom
|
||||
sta Random
|
||||
ora #$f0 ; mask to -16..0
|
||||
.TargetAbove
|
||||
ora #1 ; to avoid 0 values
|
||||
sta GenDelta ; -> delta
|
||||
lda GenCur
|
||||
.NoChangeTarget
|
||||
; Store the value in GenCur, and also
|
||||
; at the end of the TrackData array
|
||||
sta GenCur
|
||||
sta TrackData+TrackLen-1
|
||||
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
|
||||
|
||||
; 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
|
||||
|
||||
; set sprite 0
|
||||
SetSprite0: subroutine
|
||||
sta $200 ;y
|
||||
lda #1 ;code
|
||||
sta $201
|
||||
lda #0 ;flags
|
||||
sta $202
|
||||
lda #8 ;xpos
|
||||
sta $203
|
||||
rts
|
||||
|
||||
;;;;; COMMON SUBROUTINES
|
||||
|
||||
include "nesppu.asm"
|
||||
|
||||
;;;;; INTERRUPT HANDLERS
|
||||
|
||||
MAC SLEEP ;usage: SLEEP n (n>1)
|
||||
.CYCLES SET {1}
|
||||
|
||||
IF .CYCLES < 2
|
||||
ECHO "MACRO ERROR: 'SLEEP': Duration must be > 1"
|
||||
ERR
|
||||
ENDIF
|
||||
|
||||
IF .CYCLES & 1
|
||||
bit $00
|
||||
.CYCLES SET .CYCLES - 3
|
||||
ENDIF
|
||||
|
||||
REPEAT .CYCLES / 2
|
||||
nop
|
||||
REPEND
|
||||
ENDM
|
||||
|
||||
NMIHandler: subroutine
|
||||
SAVE_REGS
|
||||
; setup sky scroll
|
||||
lda Heading+1
|
||||
sta PPU_SCROLL
|
||||
lda #0
|
||||
sta PPU_SCROLL
|
||||
; load sprites
|
||||
lda #112
|
||||
jsr SetSprite0
|
||||
lda #$02
|
||||
sta PPU_OAM_DMA
|
||||
; do road calc
|
||||
jsr RoadPreSetup
|
||||
jsr PreprocessCurve
|
||||
jsr RoadPostFrame
|
||||
; wait for sprite 0
|
||||
.wait0 bit PPU_STATUS
|
||||
bvs .wait0
|
||||
.wait1 bit PPU_STATUS
|
||||
bvc .wait1
|
||||
; alter horiz. scroll position for each scanline
|
||||
ldy #0
|
||||
.loop
|
||||
tya
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
lda RoadX0,x
|
||||
sta PPU_SCROLL ; horiz byte
|
||||
lda #0
|
||||
sta PPU_SCROLL ; vert byte
|
||||
SLEEP 84
|
||||
iny
|
||||
cpy #112
|
||||
bne .loop
|
||||
RESTORE_REGS
|
||||
rti
|
||||
|
||||
;;;;; CONSTANT DATA
|
||||
|
||||
align $100
|
||||
Palette:
|
||||
hex 1f ;background
|
||||
hex 09092c00 ;bg0
|
||||
hex 09091900 ;bg1
|
||||
hex 09091500 ;bg2
|
||||
hex 09092500 ;bg3
|
||||
|
||||
;;;;; CPU VECTORS
|
||||
|
||||
NES_VECTORS
|
||||
|
||||
;;;;; TILE SETS
|
||||
|
||||
org $10000
|
||||
; background (tile) pattern table
|
||||
REPEAT 10
|
||||
;;{w:8,h:8,bpp:1,count:48,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]};;
|
||||
hex 00000000000000000000000000000000
|
||||
hex 7e42424646467e007e42424646467e00
|
||||
hex 08080818181818000808081818181800
|
||||
hex 3e22023e30303e003e22023e30303e00
|
||||
hex 3c24041e06263e003c24041e06263e00
|
||||
hex 4444447e0c0c0c004444447e0c0c0c00
|
||||
hex 3c20203e06263e003c20203e06263e00
|
||||
hex 3e22203e26263e003e22203e26263e00
|
||||
hex 3e020206060606003e02020606060600
|
||||
hex 3c24247e46467e003c24247e46467e00
|
||||
hex 3e22223e060606003e22223e06060600
|
||||
hex 3c24247e626262003c24247e62626200
|
||||
hex 7c44447e62627e007c44447e62627e00
|
||||
hex 7e42406060627e007e42406060627e00
|
||||
hex 7e42426262627e007e42426262627e00
|
||||
hex 7c40407c60607c007c40407c60607c00
|
||||
hex 3c20203c303030003c20203c30303000
|
||||
hex 7e42406e62627e007e42406e62627e00
|
||||
hex 4242427e626262004242427e62626200
|
||||
hex 10101018181818001010101818181800
|
||||
hex 0404040606467e000404040606467e00
|
||||
hex 4444447e626262004444447e62626200
|
||||
hex 2020203030303e002020203030303e00
|
||||
hex fe9292d2d2d2d200fe9292d2d2d2d200
|
||||
hex 7e424262626262007e42426262626200
|
||||
hex 7e46464242427e007e46464242427e00
|
||||
hex 7e42427e606060007e42427e60606000
|
||||
hex 7e424242424e7e007e424242424e7e00
|
||||
hex 7c44447e626262007c44447e62626200
|
||||
hex 7e42407e06467e007e42407e06467e00
|
||||
hex 7e101018181818007e10101818181800
|
||||
hex 4242426262627e004242426262627e00
|
||||
hex 646464642c2c3c00646464642c2c3c00
|
||||
hex 4949494969697f004949494969697f00
|
||||
hex 4242423c626262004242423c62626200
|
||||
hex 4242427e181818004242427e18181800
|
||||
hex 7e42027e60627e007e42027e60427e00
|
||||
hex 10101818180018001010181818001800
|
||||
hex 187e407e067e1800187e407e067e1800
|
||||
hex 00180018180000000018001818000000
|
||||
hex 00003c3c0000000000003c3c00000000
|
||||
hex 00000018180000000000001818000000
|
||||
hex 18180810000000001818081000000000
|
||||
hex 00000018180810000000001818081000
|
||||
hex 7c7c7c7c7c7c7c007c7c7c7c7c7c7c00
|
||||
hex 0000000000007c000000000000007c00
|
||||
hex 00000000000000000000000000000000
|
||||
hex 00000000000000000000000000000000
|
||||
;;
|
||||
REPEND
|
||||
REPEAT 32
|
||||
hex 00000000000000000000000000000000
|
||||
REPEND
|
@ -45,6 +45,7 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
WRAP_CLOCKS : boolean;
|
||||
jsrresult = {};
|
||||
platform : Platform;
|
||||
MAX_CYCLES : number = 2000;
|
||||
|
||||
constructor(platform : Platform) {
|
||||
this.platform = platform;
|
||||
@ -57,28 +58,45 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
}
|
||||
|
||||
traceInstructions(pc:number, minclocks:number, maxclocks:number, subaddr:number, constraints) {
|
||||
if (this.WRAP_CLOCKS) {
|
||||
if (this.pc2minclocks[pc] !== undefined)
|
||||
minclocks = Math.min(minclocks, this.pc2minclocks[pc]);
|
||||
if (this.pc2maxclocks[pc] !== undefined)
|
||||
maxclocks = Math.max(maxclocks, this.pc2maxclocks[pc]);
|
||||
}
|
||||
//console.log("trace", hex(pc), minclocks, maxclocks);
|
||||
if (!minclocks) minclocks = 0;
|
||||
if (!maxclocks) maxclocks = 0;
|
||||
if (!constraints) constraints = {};
|
||||
var modified = true;
|
||||
var abort = false;
|
||||
for (var i=0; i<1000 && modified && !abort; i++) {
|
||||
for (var i=0; modified && !abort; i++) {
|
||||
if (i >= this.MAX_CYCLES) {
|
||||
console.log("too many cycles @", hex(pc), "routine", hex(subaddr));
|
||||
break;
|
||||
}
|
||||
modified = false;
|
||||
if (this.WRAP_CLOCKS && minclocks >= this.MAX_CLOCKS) {
|
||||
// wrap clocks
|
||||
minclocks = minclocks % this.MAX_CLOCKS;
|
||||
maxclocks = maxclocks % this.MAX_CLOCKS;
|
||||
} else {
|
||||
// truncate clocks
|
||||
minclocks = Math.min(this.MAX_CLOCKS, minclocks);
|
||||
maxclocks = Math.min(this.MAX_CLOCKS, maxclocks);
|
||||
}
|
||||
var meta = this.getClockCountsAtPC(pc);
|
||||
var lob = this.platform.readAddress(pc+1);
|
||||
var hib = this.platform.readAddress(pc+2);
|
||||
var addr = lob + (hib << 8);
|
||||
var pc0 = pc;
|
||||
if (!this.pc2minclocks[pc0] || minclocks < this.pc2minclocks[pc0]) {
|
||||
if (!(minclocks >= this.pc2minclocks[pc0])) {
|
||||
this.pc2minclocks[pc0] = minclocks;
|
||||
modified = true;
|
||||
}
|
||||
if (!this.pc2maxclocks[pc0] || maxclocks > this.pc2maxclocks[pc0]) {
|
||||
if (!(maxclocks <= this.pc2maxclocks[pc0])) {
|
||||
this.pc2maxclocks[pc0] = maxclocks;
|
||||
modified = true;
|
||||
}
|
||||
//console.log(hex(pc),minclocks,maxclocks,meta);
|
||||
//console.log(hex(pc),minclocks,maxclocks,modified,meta,constraints);
|
||||
if (!meta.insnlength) {
|
||||
console.log("Illegal instruction!", hex(pc), hex(meta.opcode), meta);
|
||||
break;
|
||||
@ -94,13 +112,21 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
meta.maxCycles -= 1;
|
||||
break;
|
||||
*/
|
||||
// TODO: don't do in NES
|
||||
// TODO: only VCS
|
||||
case 0x85:
|
||||
if (lob == 0x2) { // STA WSYNC
|
||||
minclocks = maxclocks = 0;
|
||||
meta.minCycles = meta.maxCycles = 0;
|
||||
}
|
||||
break;
|
||||
// TODO: only NES (sprite 0 poll)
|
||||
case 0x2c:
|
||||
if (lob == 0x02 && hib == 0x20) { // BIT $2002
|
||||
minclocks = 0;
|
||||
maxclocks = 4; // uncertainty b/c of assumed branch poll
|
||||
meta.minCycles = meta.maxCycles = 0;
|
||||
}
|
||||
break;
|
||||
case 0x20: // JSR
|
||||
this.traceInstructions(addr, minclocks, maxclocks, addr, constraints);
|
||||
var result = this.jsrresult[addr];
|
||||
@ -115,6 +141,9 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
case 0x4c: // JMP
|
||||
pc = addr; // TODO: make sure in ROM space
|
||||
break;
|
||||
case 0x40: // RTI
|
||||
abort = true;
|
||||
break;
|
||||
case 0x60: // RTS
|
||||
if (subaddr) { // TODO: 0 doesn't work
|
||||
// TODO: combine with previous result
|
||||
@ -142,11 +171,13 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
var cons = BRANCH_CONSTRAINTS[Math.floor((meta.opcode-0x10)/0x20)];
|
||||
var cons0 = constraintEquals(oldconstraints, cons[0]);
|
||||
var cons1 = constraintEquals(oldconstraints, cons[1]);
|
||||
if (cons0 !== false) {
|
||||
// recursively trace the taken branch
|
||||
if (true || cons0 !== false) { // TODO?
|
||||
this.traceInstructions(newpc, minclocks+meta.maxCycles, maxclocks+meta.maxCycles, subaddr, cons[0]);
|
||||
}
|
||||
// abort if we will always take the branch
|
||||
if (cons1 === false) {
|
||||
console.log("abort", hex(pc), oldconstraints, cons[1]);
|
||||
console.log("branch always taken", hex(pc), oldconstraints, cons[1]);
|
||||
abort = true;
|
||||
}
|
||||
constraints = cons[1]; // not taken
|
||||
@ -156,12 +187,9 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
console.log("Instruction not supported!", hex(pc), hex(meta.opcode), meta); // TODO
|
||||
return;
|
||||
}
|
||||
minclocks = Math.min(this.MAX_CLOCKS, minclocks + meta.minCycles);
|
||||
maxclocks = Math.min(this.MAX_CLOCKS, maxclocks + meta.maxCycles);
|
||||
if (this.WRAP_CLOCKS && maxclocks >= this.MAX_CLOCKS) {
|
||||
minclocks = minclocks % this.MAX_CLOCKS;
|
||||
maxclocks = maxclocks % this.MAX_CLOCKS;
|
||||
}
|
||||
// add min/max instruction time to min/max clocks bound
|
||||
minclocks += meta.minCycles;
|
||||
maxclocks += meta.maxCycles;
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +206,7 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
|
||||
export class CodeAnalyzer_vcs extends CodeAnalyzer6502 {
|
||||
constructor(platform : Platform) {
|
||||
super(platform);
|
||||
this.MAX_CLOCKS = this.START_CLOCKS = 76*2;
|
||||
this.MAX_CLOCKS = this.START_CLOCKS = 76*2; // 2 scanlines
|
||||
this.WRAP_CLOCKS = false;
|
||||
}
|
||||
}
|
||||
@ -188,7 +216,7 @@ export class CodeAnalyzer_vcs extends CodeAnalyzer6502 {
|
||||
export class CodeAnalyzer_nes extends CodeAnalyzer6502 {
|
||||
constructor(platform : Platform) {
|
||||
super(platform);
|
||||
this.MAX_CLOCKS = 114; // ~341/3
|
||||
this.MAX_CLOCKS = 114; // 341 clocks for 3 scanlines
|
||||
this.START_CLOCKS = 0;
|
||||
this.WRAP_CLOCKS = true;
|
||||
}
|
||||
|
@ -306,11 +306,6 @@ var SampleAudio = function(clockfreq) {
|
||||
self.filterNode=self.context.createBiquadFilter();
|
||||
self.filterNode.frequency.value=6000;
|
||||
|
||||
// "LED filter" at 3275kHz - off by default
|
||||
self.lowpassNode=self.context.createBiquadFilter();
|
||||
self.lowpassNode.frequency.value=28867;
|
||||
self.filter=false;
|
||||
|
||||
// mixer
|
||||
if ( typeof self.context.createScriptProcessor === 'function') {
|
||||
self.mixerNode=self.context.createScriptProcessor(self.bufferlen, 1, 1);
|
||||
@ -326,8 +321,7 @@ var SampleAudio = function(clockfreq) {
|
||||
|
||||
// patch up some cables :)
|
||||
self.mixerNode.connect(self.filterNode);
|
||||
self.filterNode.connect(self.lowpassNode);
|
||||
self.lowpassNode.connect(self.compressorNode);
|
||||
self.filterNode.connect(self.compressorNode);
|
||||
self.compressorNode.connect(self.context.destination);
|
||||
}
|
||||
|
||||
|
@ -287,6 +287,7 @@ var OPMETA_6502 = {
|
||||
|
||||
export function getOpcodeMetadata_6502(opcode, address) {
|
||||
// TODO: more intelligent maximum cycles
|
||||
// TODO: must always be new object, b/c we might modify it
|
||||
return {
|
||||
opcode:opcode,
|
||||
minCycles:OPMETA_6502.cycletime[opcode],
|
||||
|
@ -11,17 +11,17 @@ var JSNES_PRESETS = [
|
||||
{id:'ex0.asm', name:'Initialization (ASM)'},
|
||||
{id:'ex1.asm', name:'Scrolling Demo (ASM)'},
|
||||
{id:'ex2.asm', name:'Sprite Demo (ASM)'},
|
||||
// {id:'hello.c', name:'C: Hello PPU'},
|
||||
// {id:'conio.c', name:'C: Hello Console I/O'},
|
||||
{id:'neslib1.c', name:'Text'},
|
||||
{id:'neslib2.c', name:'Sprites'},
|
||||
{id:'neslib3.c', name:'Cursor'},
|
||||
{id:'neslib4.c', name:'Metasprites'},
|
||||
{id:'neslib5.c', name:'RLE Unpack'},
|
||||
{id:'music.c', name:'Music Player'},
|
||||
{id:'musicdemo.asm', name:'Famitone Demo'},
|
||||
{id:'siegegame.c', name:'Siege Game'},
|
||||
{id:'shoot2.c', name:'Solarian Game'},
|
||||
{id:'scrollrt.asm', name:'Split Screen Scroll (ASM)'},
|
||||
{id:'road.asm', name:'3-D Road (ASM)'},
|
||||
{id:'musicdemo.asm', name:'Famitone Demo (ASM)'},
|
||||
];
|
||||
|
||||
var NES_NESLIB_PRESETS = [
|
||||
|
@ -216,7 +216,7 @@ export class SourceEditor implements ProjectView {
|
||||
setTimingResult(result:CodeAnalyzer) : void {
|
||||
this.editor.clearGutter("gutter-bytes");
|
||||
// show the lines
|
||||
for (const line in Object.keys(this.sourcefile.line2offset)) {
|
||||
for (const line of Object.keys(this.sourcefile.line2offset)) {
|
||||
var pc = this.sourcefile.line2offset[line];
|
||||
var minclocks = result.pc2minclocks[pc];
|
||||
var maxclocks = result.pc2maxclocks[pc];
|
||||
|
@ -399,7 +399,7 @@ var print_fn = function(s) {
|
||||
// test.c(6) : warning 85: in function main unreferenced local variable : 'x'
|
||||
// main.a (4): error: Unknown Mnemonic 'xxx'.
|
||||
// at 2: warning 190: ISO C forbids an empty source file
|
||||
var re_msvc = /([^(]+)\s*[(](\d+)[)]\s*:\s*(.+?):\s*(.*)/;
|
||||
var re_msvc = /[/]*([^( ]+)\s*[(](\d+)[)]\s*:\s*(.+?):\s*(.*)/;
|
||||
var re_msvc2 = /\s*(at)\s+(\d+)\s*(:)\s*(.*)/;
|
||||
|
||||
function msvcErrorMatcher(errors) {
|
||||
@ -409,7 +409,7 @@ function msvcErrorMatcher(errors) {
|
||||
var errline = parseInt(matches[2]);
|
||||
errors.push({
|
||||
line:errline,
|
||||
//path:matches[1],
|
||||
path:matches[1],
|
||||
type:matches[3],
|
||||
msg:matches[4]
|
||||
});
|
||||
@ -419,13 +419,14 @@ function msvcErrorMatcher(errors) {
|
||||
}
|
||||
}
|
||||
|
||||
function makeErrorMatcher(errors, regex, iline, imsg) {
|
||||
function makeErrorMatcher(errors, regex, iline, imsg, path) {
|
||||
return function(s) {
|
||||
var matches = regex.exec(s);
|
||||
if (matches) {
|
||||
errors.push({
|
||||
line:parseInt(matches[iline]) || 1,
|
||||
msg:matches[imsg]
|
||||
msg:matches[imsg],
|
||||
path:path
|
||||
});
|
||||
} else {
|
||||
console.log("??? "+s);
|
||||
@ -433,9 +434,9 @@ function makeErrorMatcher(errors, regex, iline, imsg) {
|
||||
}
|
||||
}
|
||||
|
||||
function extractErrors(regex, strings) {
|
||||
function extractErrors(regex, strings, path) {
|
||||
var errors = [];
|
||||
var matcher = makeErrorMatcher(errors, regex, 1, 2);
|
||||
var matcher = makeErrorMatcher(errors, regex, 1, 2, path);
|
||||
for (var i=0; i<strings.length; i++) {
|
||||
matcher(strings[i]);
|
||||
}
|
||||
@ -539,6 +540,7 @@ function parseDASMListing(code, unresolved, mainFilename) {
|
||||
var errm = re_msvc.exec(line);
|
||||
if (errm) {
|
||||
errors.push({
|
||||
path:errm[1],
|
||||
line:parseInt(errm[2]),
|
||||
msg:errm[4]
|
||||
})
|
||||
@ -876,9 +878,10 @@ function assembleSDASZ80(step) {
|
||||
function match_asm_fn(s) {
|
||||
var matches = match_asm_re.exec(s);
|
||||
if (matches) {
|
||||
var errline = parseInt(matches[2]);
|
||||
//var errline = parseInt(matches[2]);
|
||||
errors.push({
|
||||
line:1, // TODO: errline,
|
||||
line:1, // TODO
|
||||
path:step.path,
|
||||
msg:matches[1]
|
||||
});
|
||||
}
|
||||
@ -1062,7 +1065,7 @@ function preprocessMCPP(step) {
|
||||
if (!params) throw Error("Platform not supported: " + platform);
|
||||
// <stdin>:2: error: Can't open include file "foo.h"
|
||||
var errors = [];
|
||||
var match_fn = makeErrorMatcher(errors, /<stdin>:(\d+): (.+)/, 1, 2);
|
||||
var match_fn = makeErrorMatcher(errors, /<stdin>:(\d+): (.+)/, 1, 2, step.path);
|
||||
var MCPP = mcpp({
|
||||
noInitialRun:true,
|
||||
noFSInit:true,
|
||||
@ -1092,7 +1095,7 @@ function preprocessMCPP(step) {
|
||||
var errout = FS.readFile("mcpp.err", {encoding:'utf8'});
|
||||
if (errout.length) {
|
||||
// //main.c:2: error: Can't open include file "stdiosd.h"
|
||||
var errors = extractErrors(/[^:]+:(\d+): (.+)/, errout.split("\n"));
|
||||
var errors = extractErrors(/[^:]+:(\d+): (.+)/, errout.split("\n"), step.path);
|
||||
if (errors.length == 0) {
|
||||
errors = [{line:0, msg:errout}];
|
||||
}
|
||||
|
@ -15,29 +15,36 @@ global.onmessage({data:{preload:'sdcc'}});
|
||||
|
||||
// TODO: check msg against spec
|
||||
|
||||
function compile(tool, code, platform, callback, outlen, nlines, nerrors) {
|
||||
function compile(tool, code, platform, callback, outlen, nlines, nerrors, options) {
|
||||
var msgs = [{code:code, platform:platform, tool:tool, path:'src.'+tool}];
|
||||
doBuild(msgs, callback, outlen, nlines, nerrors);
|
||||
doBuild(msgs, callback, outlen, nlines, nerrors, options);
|
||||
}
|
||||
|
||||
function compileFiles(tool, files, platform, callback, outlen, nlines, nerrors) {
|
||||
function compileFiles(tool, files, platform, callback, outlen, nlines, nerrors, options) {
|
||||
var msg = {updates:[], buildsteps:[]};
|
||||
for (var fn of files) {
|
||||
var text = ab2str(fs.readFileSync('presets/'+platform+'/'+fn));
|
||||
msg.updates.push({path:fn, data:text});
|
||||
msg.buildsteps.push({path:fn, platform:platform, tool:tool});
|
||||
}
|
||||
doBuild([msg], callback, outlen, nlines, nerrors);
|
||||
doBuild([msg], callback, outlen, nlines, nerrors, options);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function doBuild(msgs, callback, outlen, nlines, nerrors) {
|
||||
function doBuild(msgs, callback, outlen, nlines, nerrors, options) {
|
||||
var msgcount = msgs.length;
|
||||
global.postMessage = function(msg) {
|
||||
if (!msg.unchanged) {
|
||||
if (msg.errors && msg.errors.length) {
|
||||
console.log(msg.errors);
|
||||
for (var err of msg.errors) {
|
||||
console.log(err);
|
||||
assert.ok(err.line >= 0);
|
||||
if (options && !options.ignoreErrorPath) {
|
||||
assert.equal(msgs[0].path, err.path);
|
||||
}
|
||||
assert.ok(err.msg);
|
||||
}
|
||||
assert.equal(nerrors, msg.errors.length, "errors");
|
||||
} else {
|
||||
assert.equal(nerrors||0, 0, "errors");
|
||||
@ -97,7 +104,10 @@ describe('Worker', function() {
|
||||
compile('cc65', 'int main() {\nint x=1;\nprintf("%d",x);\nreturn x+2;\n}', 'nes-conio', done, 0, 0, 1);
|
||||
});
|
||||
it('should NOT compile CC65 (link error)', function(done) {
|
||||
compile('cc65', 'extern void bad();\nint main() {\nbad();\nreturn 0;\n}', 'nes-conio', done, 0, 0, 1);
|
||||
compile('cc65', 'extern void bad();\nint main() {\nbad();\nreturn 0;\n}', 'nes-conio', done, 0, 0, 1, {ignoreErrorPath:true});
|
||||
});
|
||||
it('should NOT compile CC65 (preproc error)', function(done) {
|
||||
compile('cc65', '#include "NOSUCH.file"\n', 'nes-conio', done, 0, 0, 1, {ignoreErrorPath:true});
|
||||
});
|
||||
it('should assemble CA65', function(done) {
|
||||
compile('ca65', '\t.segment "HEADER"\n\t.segment "STARTUP"\n\t.segment "CHARS"\n\t.segment "VECTORS"\n\tlda #0\n\tsta $1\n', 'nes-conio', done, 40976, 2);
|
||||
@ -116,8 +126,8 @@ describe('Worker', function() {
|
||||
it('should NOT assemble SDASZ80', function(done) {
|
||||
compile('sdasz80', '\txxx hl,#0\n\tret\n', 'mw8080bw', done, 0, 0, 1);
|
||||
});
|
||||
it('should NOT assemble SDASZ80', function(done) {
|
||||
compile('sdasz80', '\tcall divxxx\n', 'mw8080bw', done, 0, 0, 1);
|
||||
it('should NOT link SDASZ80', function(done) {
|
||||
compile('sdasz80', '\tcall divxxx\n', 'mw8080bw', done, 0, 0, 1, {ignoreErrorPath:true});
|
||||
});
|
||||
it('should compile SDCC', function(done) {
|
||||
compile('sdcc', 'int foo=0; // comment\nint main(int argc) {\nint x=1;\nint y=2+argc;\nreturn x+y+argc;\n}\n', 'mw8080bw', done, 8192, 3, 0);
|
||||
@ -167,6 +177,11 @@ describe('Worker', function() {
|
||||
};
|
||||
doBuild(msgs, done2, 2799, 0, 0);
|
||||
});
|
||||
it('should NOT compile verilog example', function(done) {
|
||||
var csource = "foobar";
|
||||
var msgs = [{code:csource, platform:"verilog", tool:"verilator", dependencies:[], path:'foomain.v'}];
|
||||
doBuild(msgs, done, 0, 0, 1);
|
||||
});
|
||||
it('should compile verilog inline assembler (JSASM)', function(done) {
|
||||
var csource = ab2str(fs.readFileSync('presets/verilog/racing_game_cpu.v'));
|
||||
var dependfiles = ["hvsync_generator.v", "sprite_bitmap.v", "sprite_renderer.v", "cpu8.v"];
|
||||
@ -280,14 +295,11 @@ describe('Worker', function() {
|
||||
"buildsteps":[
|
||||
{"path":"main.c", "platform":"mw8080bw", "tool":"sdcc"},
|
||||
{"path":"fn.c", "platform":"mw8080bw", "tool":"sdcc"}
|
||||
]
|
||||
],
|
||||
"path":"fn.c"
|
||||
};
|
||||
var msgs = [m];
|
||||
doBuild(msgs, function(err, result) {
|
||||
for (var msg of result.errors)
|
||||
assert.equal(msg.path, "fn.c");
|
||||
done();
|
||||
}, 8192, [1,1], 2); // TODO: check error file
|
||||
doBuild(msgs, done, 8192, [1,1], 2); // TODO: check error file
|
||||
});
|
||||
it('should compile vicdual skeleton', function(done) {
|
||||
var files = ['skeleton.sdcc', 'cp437.c'];
|
||||
|
Loading…
x
Reference in New Issue
Block a user