nes: added road, tint demo; extra tools; embed.html fetch remote url

This commit is contained in:
Steven Hugg 2019-04-26 15:38:34 -04:00
parent 0e47e7d035
commit fe1e0fc9aa
28 changed files with 407 additions and 113 deletions

View File

@ -103,6 +103,7 @@ TODO:
- per-View keyboard shortcuts - per-View keyboard shortcuts
- parse labels - parse labels
- parse .incbin directives? - parse .incbin directives?
- can't replace in hex directives
- crt0.s compiled each time? - crt0.s compiled each time?
- debug highlight doesn't go away when debugging -> running - debug highlight doesn't go away when debugging -> running
- show breakpoint of PC or highest address on stack - show breakpoint of PC or highest address on stack
@ -124,6 +125,7 @@ TODO:
- CPU debugging - CPU debugging
- disassemble more code around breakpoint - disassemble more code around breakpoint
- single-stepping vector games makes screen fade - single-stepping vector games makes screen fade
- break on stack overflow, bad op, bad access, etc
WEB WORKER FORMAT WEB WORKER FORMAT

View File

@ -83,6 +83,14 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<a tabindex="-1" href="#">Tools</a> <a tabindex="-1" href="#">Tools</a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a class="dropdown-item" target="_8bws_tools" href="./tools/fontgen/">Bitmap Font Generator</a></li> <li><a class="dropdown-item" target="_8bws_tools" href="./tools/fontgen/">Bitmap Font Generator</a></li>
<li><a class="dropdown-item" target="_8bws_tools" href="http://tomeko.net/online_tools/file_to_hex.php?lang=en">Binary File to Hex Converter</a></li>
<li class="dropdown dropdown-submenu">
<a tabindex="-1" href="#">Atari 2600/VCS</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playerpalnext.html">playerpal 2600</a></li>
<li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playfieldpal.html">playfieldpal 2600</a></li>
</ul>
</li>
</ul> </ul>
</li> </li>
<hr> <hr>

View File

@ -26,10 +26,10 @@ Start:
lda #$1c ; $1C = light blue color lda #$1c ; $1C = light blue color
sta PPU_DATA ; $1C -> PPU data sta PPU_DATA ; $1C -> PPU data
; activate PPU graphics ; activate PPU graphics
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_COLOR lda #MASK_COLOR
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ; endless loop jmp .endless ; endless loop

View File

@ -28,10 +28,10 @@ Start:
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ; PPU scroll = $0000 sta PPU_SCROLL ; PPU scroll = $0000
; activate PPU graphics ; activate PPU graphics
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG lda #MASK_BG
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ; endless loop jmp .endless ; endless loop

View File

@ -30,10 +30,10 @@ Start:
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000 sta PPU_SCROLL ; scroll = $0000
; activate PPU graphics ; activate PPU graphics
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG lda #MASK_BG
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ; endless loop jmp .endless ; endless loop

View File

@ -34,10 +34,10 @@ Start:
sta PPU_ADDR ;PPU addr = 0 sta PPU_ADDR ;PPU addr = 0
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ;scroll = 0 sta PPU_SCROLL ;scroll = 0
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ;endless loop jmp .endless ;endless loop

View File

@ -29,10 +29,10 @@ Start:
sta PPU_ADDR ;PPU addr = 0 sta PPU_ADDR ;PPU addr = 0
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ;scroll = 0 sta PPU_SCROLL ;scroll = 0
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ;endless loop jmp .endless ;endless loop

View File

@ -287,6 +287,10 @@ void __fastcall__ nmi_set_callback(void (*callback)(void));
#define MASK_BG 0x08 #define MASK_BG 0x08
#define MASK_EDGE_SPR 0x04 #define MASK_EDGE_SPR 0x04
#define MASK_EDGE_BG 0x02 #define MASK_EDGE_BG 0x02
#define MASK_TINT_RED 0x20
#define MASK_TINT_BLUE 0x40
#define MASK_TINT_GREEN 0x80
#define MASK_MONO 0x01
#define NAMETABLE_A 0x2000 #define NAMETABLE_A 0x2000
#define NAMETABLE_B 0x2400 #define NAMETABLE_B 0x2400

View File

@ -12,8 +12,6 @@ extern const byte climbr_title_rle[];
// link title screen palette and RLE nametable // link title screen palette and RLE nametable
//#link "climbr_title.s" //#link "climbr_title.s"
void fade_in() { void fade_in() {
byte vb; byte vb;
for (vb=0; vb<=4; vb++) { for (vb=0; vb<=4; vb++) {

View File

@ -5,6 +5,8 @@
seg.u ZEROPAGE seg.u ZEROPAGE
org $0 org $0
Ptr1 .word ; for temporary pointer storage
TrackFrac .byte ; fractional position along track TrackFrac .byte ; fractional position along track
Speed .byte ; speed of car Speed .byte ; speed of car
@ -24,9 +26,8 @@ ZOfs .byte ; counter to draw striped center line
Weather .byte ; bitmask for weather Weather .byte ; bitmask for weather
Heading .word ; sky scroll pos. Heading .word ; sky scroll pos.
XCenter = 128 NumRoadScanlines = 112
NumRoadSegments = 28 NumRoadSegments = 56
; Preprocessing result: X positions for all track segments ; Preprocessing result: X positions for all track segments
RoadX0 ds NumRoadSegments RoadX0 ds NumRoadSegments
@ -43,7 +44,7 @@ InitialSpeed equ 10 ; starting speed
;;;;; NES CARTRIDGE HEADER ;;;;; NES CARTRIDGE HEADER
NES_HEADER 0,2,1,0 ; mapper 0, 2 PRGs, 1 CHR, horiz. mirror NES_HEADER 0,2,1,1 ; mapper 0, 2 PRGs, 1 CHR, vert mirror
;;;;; START OF CODE ;;;;; START OF CODE
@ -53,7 +54,6 @@ Start:
jsr ClearRAM ; clear RAM jsr ClearRAM ; clear RAM
jsr WaitSync ; wait for VSYNC (and PPU warmup) jsr WaitSync ; wait for VSYNC (and PPU warmup)
jsr SetPalette ; set palette colors
jsr FillVRAM ; set PPU video RAM jsr FillVRAM ; set PPU video RAM
jsr RoadSetup jsr RoadSetup
@ -63,10 +63,10 @@ Start:
sta PPU_ADDR ; PPU addr = $0000 sta PPU_ADDR ; PPU addr = $0000
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000 sta PPU_SCROLL ; scroll = $0000
lda #MASK_BG|MASK_SPR|MASK_BG_CLIP
sta PPU_MASK ; enable rendering (first!)
lda #CTRL_NMI lda #CTRL_NMI
sta PPU_CTRL ; enable NMI sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering
.endless .endless
jmp .endless ; endless loop jmp .endless ; endless loop
@ -249,43 +249,43 @@ GenTrack subroutine
; fill video RAM ; fill video RAM
FillVRAM: subroutine FillVRAM: subroutine
txa PPU_SETADDR $2000
ldy #$20 lda #<RoadTables
sty PPU_ADDR sta Ptr1
sta PPU_ADDR lda #>RoadTables
ldy #$10 sta Ptr1+1
ldx #8
ldy #0
.loop: .loop:
lda (Ptr1),y
sta PPU_DATA sta PPU_DATA
adc #7 iny
inx
bne .loop bne .loop
dey inc Ptr1+1
dex
bne .loop bne .loop
rts rts
; set palette colors ; set palette colors
SetPalette: subroutine SetPalette: subroutine
ldy #$00 PPU_SETADDR $3f00
lda #$3f ldx #16
sta PPU_ADDR
sty PPU_ADDR
ldx #32
.loop: .loop:
lda Palette,y lda Palette,y
sta PPU_DATA sta PPU_DATA
iny iny
dex dex
bne .loop bne .loop
rts rts
; set sprite 0 ; set sprite 0
SetSprite0: subroutine SetSprite0: subroutine
sta $200 ;y sta $200 ;ypos
lda #1 ;code lda #$00 ;code
sta $201 sta $201
lda #0 ;flags lda #$20 ;flags
sta $202 sta $202
lda #8 ;xpos lda #$fe ;xpos
sta $203 sta $203
rts rts
@ -314,18 +314,26 @@ SetSprite0: subroutine
ENDM ENDM
NMIHandler: subroutine NMIHandler: subroutine
; save registers
SAVE_REGS SAVE_REGS
; setup sky scroll ; cycle palette colors
lda Heading+1 lda TPos ; track position
sta PPU_SCROLL lsr ; / 2
lda #0 and #16 ; now either 0 or 16
sta PPU_SCROLL tay ; Y is palette offset
; load sprites jsr SetPalette ; call SetPalette
lda #112 PPU_SETADDR $2000 ; reset PPU address
; load sprite zero
lda #109
jsr SetSprite0 jsr SetSprite0
lda #$02 lda #$02
sta PPU_OAM_DMA sta PPU_OAM_DMA
; do road calc ; setup sky scroll
lda Heading+1
sta PPU_SCROLL ; X scroll
lda #0
sta PPU_SCROLL ; Y scroll = 0
; do road calculations
jsr RoadPreSetup jsr RoadPreSetup
jsr PreprocessCurve jsr PreprocessCurve
jsr RoadPostFrame jsr RoadPostFrame
@ -337,30 +345,42 @@ NMIHandler: subroutine
; alter horiz. scroll position for each scanline ; alter horiz. scroll position for each scanline
ldy #0 ldy #0
.loop .loop
; pad out rest of scanline
SLEEP 78
; change scroll register
tya tya
lsr lsr ; / 2
lsr
tax tax
lda RoadX0,x lda RoadX0,x ; get X offset of scanline
eor #$80 ; + 128
sta PPU_SCROLL ; horiz byte sta PPU_SCROLL ; horiz byte
lda #0 lda #0
sta PPU_SCROLL ; vert byte sta PPU_SCROLL ; vert byte = 0
SLEEP 84 ; take extra cycle every 4th line
tya
and #3
bne .skipcyc
.skipcyc
; next loop iteration
iny iny
cpy #112 cpy #NumRoadScanlines
bne .loop bne .loop ; do next scanline
; restore registers and return from interrupt
RESTORE_REGS RESTORE_REGS
rti rti
;;;;; CONSTANT DATA ;;;;; CONSTANT DATA
align $100 ;;{pal:"nes",layout:"nes"};;
Palette: Palette:
hex 1f ;background hex 0F3F06300F19063F0F1916063F180801
hex 09092c00 ;bg0 hex 0F30163F0F19163F0F1906160F180801
hex 09091900 ;bg1 ;;
hex 09091500 ;bg2 RoadTables:
hex 09092500 ;bg3 incbin "road/nametable.dat"
incbin "road/attribute.dat"
incbin "road/nametable1.dat"
incbin "road/attribute1.dat"
;;;;; CPU VECTORS ;;;;; CPU VECTORS
@ -369,4 +389,4 @@ Palette:
;;;;; TILE SETS ;;;;; TILE SETS
org $10000 org $10000
incbin "jroatch.chr" incbin "road/road.chr"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
presets/nes/road/road.chr Normal file

Binary file not shown.

View File

@ -5,6 +5,8 @@
seg.u ZEROPAGE seg.u ZEROPAGE
org $0 org $0
SkipY ds 1
;;;;; OTHER VARIABLES ;;;;; OTHER VARIABLES
@ -34,10 +36,10 @@ Start:
sta PPU_ADDR ; PPU addr = $0000 sta PPU_ADDR ; PPU addr = $0000
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000 sta PPU_SCROLL ; scroll = $0000
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ; endless loop jmp .endless ; endless loop
@ -69,7 +71,7 @@ SetPalette: subroutine
; set sprite 0 ; set sprite 0
SetSprite0: subroutine SetSprite0: subroutine
sta $200 ;y sta $200 ;y
lda #$01 ;code lda #$a0 ;code
sta $201 sta $201
lda #$20 ;flags lda #$20 ;flags
sta $202 sta $202
@ -100,6 +102,13 @@ NMIHandler: subroutine
bvc .wait1 bvc .wait1
ldy #0 ldy #0
.loop .loop
; take out cycle every 4th line
tya
and #3
bne .skipcyc ; clks = 2/3/3/3
.skipcyc
; pad out rest of scanline
SLEEP 65
; alter horiz. scroll position for each scanline ; alter horiz. scroll position for each scanline
tya tya
sec sec
@ -111,10 +120,9 @@ NMIHandler: subroutine
sta PPU_SCROLL ; horiz byte sta PPU_SCROLL ; horiz byte
lda #0 lda #0
sta PPU_SCROLL ; vert byte sta PPU_SCROLL ; vert byte
; pad out rest of scanline ; next iteration of loop
SLEEP 72
iny iny
cpy #224 cpy #112
bne .loop bne .loop
RESTORE_REGS RESTORE_REGS
rti rti

View File

@ -1,16 +1,45 @@
#include <stdlib.h>
#include <string.h>
// include NESLIB header
#include "neslib.h" #include "neslib.h"
// link the pattern table into CHR ROM // link the pattern table into CHR ROM
//#link "chr_generic.s" //#link "chr_generic.s"
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // screen color
0x11,0x30,0x27,0x0, // background palette 0
0x1c,0x20,0x2c,0x0, // background palette 1
0x00,0x10,0x20,0x0, // background palette 2
0x06,0x16,0x26,0x0, // background palette 3
0x16,0x35,0x24,0x0, // sprite palette 0
0x00,0x37,0x25,0x0, // sprite palette 1
0x0d,0x2d,0x3a,0x0, // sprite palette 2
0x0d,0x27,0x2a // sprite palette 3
};
// setup PPU and tables
void setup_graphics() {
// clear sprites
oam_clear();
// set palette colors
pal_all(PALETTE);
}
void main(void) void main(void)
{ {
pal_col(1,0x04); setup_graphics();
pal_col(2,0x20); // draw message
pal_col(3,0x30);
vram_adr(NTADR_A(2,2)); vram_adr(NTADR_A(2,2));
vram_write("HELLO, WORLD!", 12); vram_write("HELLO, WORLD!", 12);
ppu_on_all();//enable rendering // enable rendering
while(1);//do nothing, infinite loop ppu_on_all();
// infinite loop
while(1) {
}
} }

69
presets/nes/tint.c Normal file
View File

@ -0,0 +1,69 @@
#include <stdlib.h>
#include <string.h>
// include NESLIB header
#include "neslib.h"
// link the pattern table into CHR ROM
//#link "chr_generic.s"
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x2D, // screen color
0x00,0x30,0x30,0x00, // background palette 0
0x0C,0x20,0x2C,0x00, // background palette 1
0x14,0x10,0x25,0x00, // background palette 2
0x17,0x16,0x28,0x00, // background palette 3
0x16,0x35,0x24,0x00, // sprite palette 0
0x00,0x37,0x25,0x00, // sprite palette 1
0x0D,0x2D,0x3A,0x00, // sprite palette 2
0x0D,0x27,0x2A // sprite palette 3
};
// setup PPU and tables
void setup_graphics() {
// clear sprites
oam_clear();
// set palette colors
pal_all(PALETTE);
}
void main(void)
{
byte i;
setup_graphics();
// draw message
for (i=0; i<30; i++) {
vram_adr(NTADR_A(1,i));
// vram_write("\x18\x18 USE CONTROLLER FOR TINT \x18\x18\x18", 30);
vram_write(" A:red B:green \x1e\x1f:blue \x1c\x1d:mono", 30);
}
// attributes
vram_adr(0x23c0);
vram_fill(0x00, 8);
vram_fill(0x55, 8);
vram_fill(0xaa, 8);
vram_fill(0xff, 8);
vram_fill(0x11, 8);
vram_fill(0x33, 8);
vram_fill(0xdd, 8);
// enable rendering
ppu_on_all();
// infinite loop
while(1) {
byte pad = pad_poll(0);
byte mask = MASK_BG;
if (pad & PAD_A)
mask |= MASK_TINT_RED;
if (pad & PAD_B)
mask |= MASK_TINT_GREEN;
if (pad & (PAD_LEFT|PAD_RIGHT))
mask |= MASK_TINT_BLUE;
if (pad & (PAD_UP|PAD_DOWN))
mask |= MASK_MONO;
ppu_mask(mask);
}
}

View File

@ -34,10 +34,10 @@ Start:
sta PPU_ADDR ; PPU addr = $0000 sta PPU_ADDR ; PPU addr = $0000
sta PPU_SCROLL sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000 sta PPU_SCROLL ; scroll = $0000
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless .endless
jmp .endless ; endless loop jmp .endless ; endless loop
@ -93,26 +93,26 @@ NMIHandler: subroutine
; load sprites ; load sprites
lda #$02 lda #$02
sta PPU_OAM_DMA sta PPU_OAM_DMA
; wait for sprite 0
.wait0 bit PPU_STATUS
bvs .wait0
.wait1 bit PPU_STATUS
bvc .wait1
; set XY scroll ; set XY scroll
; compute first PPU_ADDR write ; compute second PPU_ADDR write
lda ScrollX lda ScrollX
tax tax ; ScrollX -> X
lsr lsr
lsr lsr
lsr lsr
sta Temp sta Temp
lda ScrollY lda ScrollY
tay tay ; ScrollY -> Y
and #$f8 and #$38
asl asl
asl asl
ora Temp ora Temp ; (ScrollX >> 3) | ((ScrollY & 0x38) << 2)
pha pha ; push onto stack
; wait for sprite 0
.wait0 bit PPU_STATUS
bvs .wait0
.wait1 bit PPU_STATUS
bvc .wait1
; set PPU_ADDR.1 ; set PPU_ADDR.1
lda #0 lda #0
sta PPU_ADDR sta PPU_ADDR

View File

@ -3,7 +3,7 @@ window['Javatari'].AUTO_START = false;
import { PLATFORMS } from "./emu"; import { PLATFORMS } from "./emu";
import { Platform } from "./baseplatform"; import { Platform } from "./baseplatform";
import { stringToByteArray } from "./util"; import { stringToByteArray, getWithBinary } from "./util";
export var platform_id : string; // platform ID string export var platform_id : string; // platform ID string
export var platform : Platform; // platform object export var platform : Platform; // platform object
@ -67,17 +67,37 @@ function addPageFocusHandlers() {
}); });
} }
function startROM(title, rom) {
if (!rom ) {
alert("No ROM found.");
return;
}
console.log(rom.length + ' bytes');
platform.loadROM(title, rom);
platform.resume();
}
function startPlatform(qs) { function startPlatform(qs) {
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'."); if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
platform = new PLATFORMS[platform_id]($("#emulator")[0]); platform = new PLATFORMS[platform_id]($("#emulator")[0]);
platform.start(); platform.start();
var title = qs['n'] || 'Game'; var title = qs['n'] || 'Game';
var rom : Uint8Array;
var romurl = qs['url'];
var lzgvar = qs['r']; var lzgvar = qs['r'];
var lzgrom = stringToByteArray(atob(lzgvar)); if (romurl) {
var rom = new lzgmini().decode(lzgrom); // load rom url remotely
console.log(rom.length + ' bytes'); console.log(romurl);
platform.loadROM(title, rom); getWithBinary(romurl, (data) => {
platform.resume(); startROM(title, data);
}, 'arraybuffer');
return true;
} else if (lzgvar) {
// decompress from lzg
var lzgrom = stringToByteArray(atob(lzgvar));
rom = new lzgmini().decode(lzgrom);
}
startROM(title, rom);
return true; return true;
} }

View File

@ -16,6 +16,7 @@ const JSNES_PRESETS = [
{id:'metasprites.c', name:'Metasprites'}, {id:'metasprites.c', name:'Metasprites'},
{id:'flicker.c', name:'Flickering Sprites'}, {id:'flicker.c', name:'Flickering Sprites'},
{id:'metacursor.c', name:'Controllers'}, {id:'metacursor.c', name:'Controllers'},
{id:'tint.c', name:'Color Emphasis'},
{id:'rletitle.c', name:'Title Screen RLE'}, {id:'rletitle.c', name:'Title Screen RLE'},
{id:'statusbar.c', name:'Split Status Bar'}, {id:'statusbar.c', name:'Split Status Bar'},
{id:'horizmask.c', name:'Offscreen Scrolling'}, {id:'horizmask.c', name:'Offscreen Scrolling'},
@ -34,8 +35,9 @@ const JSNES_PRESETS = [
{id:'ex3.asm', name:'Sprite Demo (ASM)'}, {id:'ex3.asm', name:'Sprite Demo (ASM)'},
{id:'ex4.asm', name:'Controller Demo (ASM)'}, {id:'ex4.asm', name:'Controller Demo (ASM)'},
{id:'musicdemo.asm', name:'Famitone Demo (ASM)'}, {id:'musicdemo.asm', name:'Famitone Demo (ASM)'},
{id:'scrollrt.asm', name:'Line-by-line Scrolling (ASM)'},
{id:'xyscroll.asm', name:'XY Split Scrolling (ASM)'}, {id:'xyscroll.asm', name:'XY Split Scrolling (ASM)'},
{id:'scrollrt.asm', name:'Line-by-line Scrolling (ASM)'},
{id:'road.asm', name:'3-D Road Demo (ASM)'},
]; ];
/// JSNES /// JSNES

View File

@ -1,7 +1,7 @@
"use strict"; "use strict";
import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, Segment, WorkerResult } from "./workertypes"; import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, Segment, WorkerResult } from "./workertypes";
import { getFilenameForPath, getFilenamePrefix, getFolderForPath, isProbablyBinary } from "./util"; import { getFilenamePrefix, getFolderForPath, isProbablyBinary } from "./util";
type BuildResultCallback = (result:WorkerResult) => void; type BuildResultCallback = (result:WorkerResult) => void;
type BuildStatusCallback = (busy:boolean) => void; type BuildStatusCallback = (busy:boolean) => void;
@ -153,7 +153,7 @@ export class CodeProject {
this.preloadWorker(this.mainpath); this.preloadWorker(this.mainpath);
var msg = {updates:[], buildsteps:[]}; var msg = {updates:[], buildsteps:[]};
// TODO: add preproc directive for __MAINFILE__ // TODO: add preproc directive for __MAINFILE__
var mainfilename = getFilenameForPath(this.mainpath); var mainfilename = this.stripLocalPath(this.mainpath);
var maintext = this.getFile(this.mainpath); var maintext = this.getFile(this.mainpath);
var depfiles = []; var depfiles = [];
msg.updates.push({path:mainfilename, data:maintext}); msg.updates.push({path:mainfilename, data:maintext});
@ -177,10 +177,10 @@ export class CodeProject {
// TODO: get local file as well as presets? // TODO: get local file as well as presets?
loadFiles(paths:string[], callback:LoadFilesCallback) { loadFiles(paths:string[], callback:LoadFilesCallback) {
var result : Dependency[] = []; var result : Dependency[] = [];
function addResult(path, data) { var addResult = (path, data) => {
result.push({ result.push({
path:path, path:path,
filename:getFilenameForPath(path), filename:this.stripLocalPath(path),
link:true, link:true,
data:data data:data
}); });
@ -319,7 +319,7 @@ export class CodeProject {
// returns first listing in format [prefix].lst (TODO: could be better) // returns first listing in format [prefix].lst (TODO: could be better)
getListingForFile(path) : CodeListing { getListingForFile(path) : CodeListing {
var fnprefix = getFilenamePrefix(getFilenameForPath(path)); var fnprefix = getFilenamePrefix(this.stripLocalPath(path));
var listings = this.getListings(); var listings = this.getListings();
for (var lstfn in listings) { for (var lstfn in listings) {
if (getFilenamePrefix(lstfn) == fnprefix) { if (getFilenamePrefix(lstfn) == fnprefix) {
@ -327,4 +327,15 @@ export class CodeProject {
} }
} }
} }
stripLocalPath(path : string) : string {
// TODO: strip main path as well
if (path.startsWith('local/')) {
path = path.substring(6);
}
if (path.startsWith('share/')) {
path = path.substring(6);
}
return path;
}
} }

View File

@ -12,7 +12,7 @@ import { PLATFORMS, EmuHalt, Toolbar } from "./emu";
import * as Views from "./views"; import * as Views from "./views";
import { createNewPersistentStore } from "./store"; import { createNewPersistentStore } from "./store";
import { getFilenameForPath, getFilenamePrefix, highlightDifferences, invertMap, byteArrayToString, compressLZG, import { getFilenameForPath, getFilenamePrefix, highlightDifferences, invertMap, byteArrayToString, compressLZG,
byteArrayToUTF8, isProbablyBinary } from "./util"; byteArrayToUTF8, isProbablyBinary, getWithBinary } from "./util";
import { StateRecorderImpl } from "./recorder"; import { StateRecorderImpl } from "./recorder";
// external libs (TODO) // external libs (TODO)
@ -101,22 +101,6 @@ function setLastPreset(id:string) {
} }
} }
// firefox doesn't do GET with binary files
function getWithBinary(url:string, success:(text:FileData)=>void, datatype:'text'|'arraybuffer') {
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = datatype;
oReq.onload = function (oEvent) {
if (oReq.status == 200)
success(oReq.response);
else if (oReq.status == 404)
success(null);
else
throw "Error " + oReq.status + " loading " + url;
}
oReq.send(null);
}
function initProject() { function initProject() {
current_project = new CodeProject(newWorker(), platform_id, platform, store); current_project = new CodeProject(newWorker(), platform_id, platform, store);
projectWindows = new ProjectWindows($("#workspace")[0] as HTMLElement, current_project); projectWindows = new ProjectWindows($("#workspace")[0] as HTMLElement, current_project);

View File

@ -320,7 +320,7 @@ export function isProbablyBinary(path:string, data?:number[] | Uint8Array) : boo
// check extensions // check extensions
if (path) { if (path) {
path = path.toUpperCase(); path = path.toUpperCase();
const BINEXTS = ['.CHR','.BIN','.PAL','.NAM','.RLE','.LZ4']; const BINEXTS = ['.CHR','.BIN','.DAT','.PAL','.NAM','.RLE','.LZ4'];
for (var ext of BINEXTS) { for (var ext of BINEXTS) {
if (path.endsWith(ext)) score++; if (path.endsWith(ext)) score++;
} }
@ -446,3 +446,25 @@ export function rle_unpack(src : Uint8Array) : Uint8Array {
} }
return new Uint8Array(dest); return new Uint8Array(dest);
} }
// firefox doesn't do GET with binary files
export function getWithBinary(url:string, success:(text:string|Uint8Array)=>void, datatype:'text'|'arraybuffer') {
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = datatype;
oReq.onload = function (oEvent) {
if (oReq.status == 200) {
var data = oReq.response;
if (data instanceof ArrayBuffer) {
data = new Uint8Array(data);
}
success(data);
} else if (oReq.status == 404) {
success(null);
} else {
throw "Error " + oReq.status + " loading " + url;
}
}
oReq.send(null);
}

View File

@ -342,6 +342,15 @@ function populateEntry(fs, path:string, entry:FileEntry, options:BuildOptions) {
var data = entry.data; var data = entry.data;
if (options && options.processFn) if (options && options.processFn)
data = options.processFn(data); data = options.processFn(data);
// create subfolders
var toks = path.split('/');
if (toks.length > 1) {
for (var i=0; i<toks.length-1; i++)
try {
fs.mkdir(toks[i]);
} catch (e) { }
}
// write file
fs.writeFile(path, data, {encoding:entry.encoding}); fs.writeFile(path, data, {encoding:entry.encoding});
fs.utime(path, entry.ts, entry.ts); fs.utime(path, entry.ts, entry.ts);
console.log("<<<", path, entry.data.length); console.log("<<<", path, entry.data.length);

6
tools/nes/Makefile Normal file
View File

@ -0,0 +1,6 @@
nametable.dat: road.png
makechr -e error.png $< #-b 0000ff
road.png: road.py
python road.py

102
tools/nes/road.py Executable file
View File

@ -0,0 +1,102 @@
#!/usr/bin/python
# Import a library of functions called 'pygame'
import pygame
import random
from math import pi
# Initialize the game engine
pygame.init()
# Define the colors we will use in RGB format
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
BLUE = ( 0, 0, 255)
GREEN = ( 0, 184, 0)
CURBING = [
(136,20,0),
(168,16,0),
]
CENLINE = [
(124,124,124),
(188,188,188),
]
MOUNTAINS = [
(80,48,0),
(172,124,0)
]
# Set the height and width of the screen
size = [512, 240]
y0 = 112
x0 = 256
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Example code for the draw module")
#Loop until the user clicks the close button.
done = False
clock = pygame.time.Clock()
while not done:
# This limits the while loop to a max of 10 times per second.
# Leave this out and we will use all CPU we can.
clock.tick(10)
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
# All drawing code happens after the for loop and but
# inside the main while done==False loop.
# Clear the screen and set the screen background
screen.fill(BLUE)
pygame.draw.rect(screen, GREEN, [0, y0, 512, 240-y0])
# draw the road
for y in range(y0,240):
i = y-y0
rw = i*2
cw = rw/4
lw = rw/32
z = 500.0/(i+1)
curbcol = CURBING[int(z) % 2]
cencol = CENLINE[int(z) % 2]
if i < 16:
cencol = BLACK #CENLINE[0]
if i < 0:
curbcol = BLACK #CURBING[0]
pygame.draw.line(screen, BLACK, [x0-rw, y], [x0+rw, y], 1)
pygame.draw.line(screen, curbcol, [x0-rw-cw, y], [x0-rw, y], 1)
pygame.draw.line(screen, curbcol, [x0+rw, y], [x0+rw+cw, y], 1)
pygame.draw.line(screen, cencol, [x0-rw/3-lw, y], [x0-rw/3+lw, y], 1)
pygame.draw.line(screen, cencol, [x0+rw/3-lw, y], [x0+rw/3+lw, y], 1)
# draw mountains
h1 = 1
h2 = 2
for x in range(0,512):
pygame.draw.line(screen, MOUNTAINS[0], [x, y0-1], [x, y0-h1], 1)
pygame.draw.line(screen, MOUNTAINS[1], [x, y0-1], [x, y0-h2], 1)
if random.randint(0,8) > h1:
h1 += 1
elif h1 > 1:
h1 -= 1
if random.randint(0,6) > h2:
h2 += 1
elif h2 > 1:
h2 -= 1
# Go ahead and update the screen with what we've drawn.
# This MUST happen after all the other drawing commands.
pygame.display.flip()
pygame.image.save(screen, 'road.png')
# Be IDLE friendly
pygame.quit()