mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-10 16:29:48 +00:00
Merge branch 'master' of github.com:sehugg/8bitworkshop
This commit is contained in:
commit
daa6acbac8
@ -138,10 +138,6 @@ div.mem_info a.selected {
|
||||
.btn_recording {
|
||||
color: #ff3333;
|
||||
}
|
||||
.seg_code { color: #ff9966; }
|
||||
.seg_data { color: #66ff66; }
|
||||
.seg_stack { color: #ffff66; }
|
||||
.seg_unknown { color: #cccccc; }
|
||||
span.hilite {
|
||||
color: #ff66ff;
|
||||
}
|
||||
@ -413,6 +409,11 @@ div.markdown th {
|
||||
border-color: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.seg_code { color: #ccddff; }
|
||||
.seg_data { color: #aaeeaa; }
|
||||
.seg_io { color: #ffcccc; }
|
||||
.seg_stack { color: #ffff66; }
|
||||
.seg_unknown { color: #cccccc; }
|
||||
.segment.segment-ram {
|
||||
background-color:#aaeeaa;
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ TODO:
|
||||
- game starts even if switched away before first load
|
||||
- vcs: break on # of lines changed (maybe using getRasterPosition?)
|
||||
- profiler restarts when paused
|
||||
- it's pretty easy to add a new file named like a library file (bcd.c)
|
||||
|
||||
WEB WORKER FORMAT
|
||||
|
||||
|
@ -43,15 +43,25 @@
|
||||
#define APU_PULSE_CONTROL(channel,duty,decay)\
|
||||
APU.pulse[channel].control = (duty) | (decay);
|
||||
|
||||
#define APU_PULSE_SWEEP(channel,period,shift,up)\
|
||||
APU.pulse[channel].ramp = 0x80 | (period<<4) | (up?8:0) | shift;
|
||||
|
||||
#define APU_PULSE_SWEEP_DISABLE(channel)\
|
||||
APU.pulse[channel].ramp = 0;
|
||||
|
||||
// triangle channel
|
||||
#define TRIANGLE_LC_HALT 0x80
|
||||
#define TRIANGLE_LC_MASK 0x7f
|
||||
|
||||
#define APU_TRIANGLE_LENGTH(period,len)\
|
||||
APU.triangle.counter = 0x7f;\
|
||||
APU.triangle.period_low = (period)&0xff;\
|
||||
APU.triangle.len_period_high = (((period)>>8)&7) | ((len)<<3);
|
||||
|
||||
#define APU_TRIANGLE_SUSTAIN(period)\
|
||||
APU.triangle.counter = 0xc0;\
|
||||
APU.triangle.period_low = (period) & 0xff;\
|
||||
APU.triangle.len_period_high = (period) >> 8;
|
||||
APU.triangle.counter = 0xff;\
|
||||
APU.triangle.period_low = (period)&0xff;\
|
||||
APU.triangle.len_period_high = (((period)>>8)&7);
|
||||
|
||||
// noise channel
|
||||
#define NOISE_ENVLOOP 0x20
|
||||
|
100
presets/nes/aputest.c
Normal file
100
presets/nes/aputest.c
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "neslib.h"
|
||||
|
||||
#include "apu.h"
|
||||
//#link "apu.c"
|
||||
|
||||
// link the pattern table into CHR ROM
|
||||
//#link "chr_generic.s"
|
||||
|
||||
typedef struct APUParam {
|
||||
byte chmask;
|
||||
const char* name;
|
||||
word valmask;
|
||||
} APUParam;
|
||||
|
||||
#define APU_DEFCOUNT 20
|
||||
|
||||
const APUParam APU_DEFS[APU_DEFCOUNT] = {
|
||||
{0x01, "Pulse1 Period", 0x7ff },
|
||||
{0x01, "Pulse1 Duty", 0xc0 },
|
||||
{0x01, "Pulse1 Decay", 0x0f },
|
||||
{0x01, "Pulse1 Length", 0x0f },
|
||||
{0x01, "Pulse1 Sweep Period", 0x07 },
|
||||
{0x01, "Pulse1 Sweep Rate", 0x07 },
|
||||
{0x01, "Pulse1 Sweep Up?", 0x01 },
|
||||
{0x02, "Pulse2 Period", 0x7ff },
|
||||
{0x02, "Pulse2 Duty", 0xc0 },
|
||||
{0x02, "Pulse2 Decay", 0x0f },
|
||||
{0x02, "Pulse2 Length", 0x0f },
|
||||
{0x02, "Pulse2 Sweep Period", 0x07 },
|
||||
{0x02, "Pulse2 Sweep Rate", 0x07 },
|
||||
{0x02, "Pulse2 Sweep Up?", 0x01 },
|
||||
{0x04, "Triangle Period", 0x7ff },
|
||||
{0x04, "Triangle Length", 0x0f },
|
||||
{0x08, "Noise Period", 0x0f },
|
||||
{0x08, "Noise Decay", 0x0f },
|
||||
{0x08, "Noise Length", 0x0f },
|
||||
{0x08, "Noise Buzz", NOISE_PERIOD_BUZZ },
|
||||
};
|
||||
|
||||
word enmask;
|
||||
word vals[APU_DEFCOUNT];
|
||||
|
||||
void random_sound() {
|
||||
byte i;
|
||||
|
||||
do {
|
||||
enmask = rand() & 15; // all except DMC
|
||||
} while (enmask == 0);
|
||||
|
||||
for (i=0; i<APU_DEFCOUNT; i++) {
|
||||
vals[i] = rand() & APU_DEFS[i].valmask;
|
||||
}
|
||||
}
|
||||
|
||||
void print_sound() {
|
||||
byte i;
|
||||
char buf[32];
|
||||
for (i=0; i<APU_DEFCOUNT; i++) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (enmask & APU_DEFS[i].chmask) {
|
||||
sprintf(buf, "%2d %19s %5d", i, APU_DEFS[i].name, vals[i]);
|
||||
}
|
||||
vram_adr(NTADR_A(1,i+1));
|
||||
vram_write(buf, 32);
|
||||
}
|
||||
}
|
||||
|
||||
void play_sound() {
|
||||
APU_ENABLE(enmask);
|
||||
APU_PULSE_DECAY(0, vals[0], vals[1], vals[2], vals[3]);
|
||||
APU_PULSE_SWEEP(0, vals[4], vals[5], vals[6]);
|
||||
APU_PULSE_DECAY(1, vals[7], vals[8], vals[9], vals[10]);
|
||||
APU_PULSE_SWEEP(1, vals[11], vals[12], vals[13]);
|
||||
APU_TRIANGLE_LENGTH(vals[14], vals[15]);
|
||||
APU_NOISE_DECAY(vals[16]|vals[19], vals[17], vals[18]);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
pal_col(1,0x04);
|
||||
pal_col(2,0x20);
|
||||
pal_col(3,0x30);
|
||||
vram_adr(NTADR_A(0,26));
|
||||
vram_write(" Space=New Sound, Enter=Replay ", 32);
|
||||
apu_init();
|
||||
while(1) {
|
||||
ppu_off();
|
||||
if (!(pad_state(0) & PAD_START)) {
|
||||
random_sound();
|
||||
}
|
||||
print_sound();
|
||||
play_sound();
|
||||
ppu_on_all();//enable rendering
|
||||
while (!pad_trigger(0)) ; // wait for key
|
||||
}
|
||||
}
|
@ -2,21 +2,12 @@
|
||||
#include "neslib.h"
|
||||
|
||||
word bcd_add(word a, word b) {
|
||||
word result = 0;
|
||||
byte c = 0;
|
||||
byte shift = 0;
|
||||
while (shift < 16) {
|
||||
byte d = (a & 0xf) + (b & 0xf) + c;
|
||||
c = 0;
|
||||
while (d >= 10) {
|
||||
++c;
|
||||
d -= 10;
|
||||
}
|
||||
result |= d << shift;
|
||||
shift += 4;
|
||||
a >>= 4;
|
||||
b >>= 4;
|
||||
}
|
||||
return result;
|
||||
register word c, d; // intermediate values
|
||||
c = a + 0x0666; // add 6 to each BCD digit
|
||||
d = c ^ b; // sum without carry propagation
|
||||
c += b; // provisional sum
|
||||
d = ~(c ^ d) & 0x1110; // just the BCD carry bits
|
||||
d = (d >> 2) | (d >> 3); // correction
|
||||
return c - d; // corrected BCD sum
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
|
||||
unsigned int bcd_add(unsigned int a, unsigned int b);
|
||||
unsigned int bcd_add2(unsigned int a, unsigned int b);
|
||||
|
File diff suppressed because one or more lines are too long
@ -109,11 +109,11 @@ NES_MIRR_QUAD = 8
|
||||
;;;;; 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)
|
||||
seg Vectors ; segment "Vectors"
|
||||
org $fffa ; start at address $fffa
|
||||
.word NMIHandler ; $fffa vblank nmi
|
||||
.word Start ; $fffc reset
|
||||
.word NMIHandler ; $fffe irq / brk
|
||||
ENDM
|
||||
|
||||
;;;;; PPU_SETADDR <address> - set 16-bit PPU address
|
||||
|
@ -2,22 +2,22 @@
|
||||
;;;;; SUBROUTINES
|
||||
|
||||
ClearRAM: subroutine
|
||||
lda #0
|
||||
tax
|
||||
lda #0 ; A = 0
|
||||
tax ; X = 0
|
||||
.clearRAM
|
||||
sta $0,x
|
||||
cpx #$fe ; don't clear last 2 bytes of stack
|
||||
bcs .skipStack
|
||||
sta $100,x
|
||||
sta $0,x ; clear $0-$ff
|
||||
cpx #$fe ; last 2 bytes of stack?
|
||||
bcs .skipStack ; don't clear it
|
||||
sta $100,x ; clear $100-$1fd
|
||||
.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
|
||||
sta $200,x ; clear $200-$2ff
|
||||
sta $300,x ; clear $300-$3ff
|
||||
sta $400,x ; clear $400-$4ff
|
||||
sta $500,x ; clear $500-$5ff
|
||||
sta $600,x ; clear $600-$6ff
|
||||
sta $700,x ; clear $700-$7ff
|
||||
inx ; X = X + 1
|
||||
bne .clearRAM ; loop 256 times
|
||||
rts
|
||||
|
||||
; wait for VSYNC to start
|
||||
|
@ -8,17 +8,11 @@
|
||||
#define VBUFSIZE 128
|
||||
|
||||
// update buffer starts at $100 (stack page)
|
||||
#define updbuf ((byte* const)0x100)
|
||||
#define updbuf ((byte*)0x100)
|
||||
|
||||
// index to end of buffer
|
||||
extern byte updptr;
|
||||
|
||||
// macro to add a multibyte header
|
||||
#define VRAMBUF_PUT(addr,len,flags)\
|
||||
VRAMBUF_ADD(((addr) >> 8) | (flags));\
|
||||
VRAMBUF_ADD(addr);\
|
||||
VRAMBUF_ADD(len);
|
||||
|
||||
// macro to set a single byte in buffer
|
||||
#define VRAMBUF_SET(b)\
|
||||
__A__ = (b);\
|
||||
@ -30,6 +24,16 @@ extern byte updptr;
|
||||
VRAMBUF_SET(b)\
|
||||
asm("inc %v", updptr);
|
||||
|
||||
// C versions of macros
|
||||
//#define VRAMBUF_SET(b) updbuf[updptr] = (b);
|
||||
//#define VRAMBUF_ADD(b) VRAMBUF_SET(b); ++updptr
|
||||
|
||||
// macro to add a raw header (useful for single bytes)
|
||||
#define VRAMBUF_PUT(addr,len,flags)\
|
||||
VRAMBUF_ADD(((addr) >> 8) | (flags));\
|
||||
VRAMBUF_ADD(addr);\
|
||||
VRAMBUF_ADD(len);
|
||||
|
||||
// add EOF marker to buffer (but don't increment pointer)
|
||||
void cendbuf(void);
|
||||
|
||||
|
@ -73,6 +73,7 @@ export interface Platform {
|
||||
inspect?(ident:string) : string;
|
||||
disassemble?(addr:number, readfn:(addr:number)=>number) : DisasmLine;
|
||||
readAddress?(addr:number) : number;
|
||||
readVRAMAddress?(addr:number) : number;
|
||||
setFrameRate?(fps:number) : void;
|
||||
getFrameRate?() : number;
|
||||
|
||||
|
@ -26,6 +26,7 @@ const JSNES_PRESETS = [
|
||||
{id:'statusbar.c', name:'Split Status Bar'},
|
||||
{id:'horizmask.c', name:'Offscreen Scrolling'},
|
||||
{id:'attributes.c', name:'Attribute Table + Pixels'},
|
||||
{id:'aputest.c', name:'Sound Tester'},
|
||||
{id:'music.c', name:'Music Player'},
|
||||
{id:'siegegame.c', name:'Siege Game'},
|
||||
{id:'shoot2.c', name:'Solarian Game'},
|
||||
@ -233,6 +234,9 @@ const _JSNESPlatform = function(mainElement) {
|
||||
getRasterScanline() : number {
|
||||
return nes.ppu.scanline;
|
||||
}
|
||||
readVRAMAddress(addr : number) : number {
|
||||
return nes.ppu.vramMem[addr & 0x7fff];
|
||||
}
|
||||
|
||||
getCPUState() {
|
||||
var c = nes.cpu.toJSON();
|
||||
|
@ -210,6 +210,11 @@ function refreshWindowList() {
|
||||
return new Views.MemoryView();
|
||||
});
|
||||
}
|
||||
if (platform.readVRAMAddress) {
|
||||
addWindowItem("#memvram", "VRAM Browser", function() {
|
||||
return new Views.VRAMMemoryView();
|
||||
});
|
||||
}
|
||||
if (current_project.segments) {
|
||||
addWindowItem("#memmap", "Memory Map", function() {
|
||||
return new Views.MemoryMapView();
|
||||
|
48
src/views.ts
48
src/views.ts
@ -659,7 +659,7 @@ export class MemoryView implements ProjectView {
|
||||
for (var i=0; i<n1; i++) s += ' ';
|
||||
if (n1 > 8) s += ' ';
|
||||
for (var i=n1; i<n2; i++) {
|
||||
var read = platform.readAddress(offset+i);
|
||||
var read = this.readAddress(offset+i);
|
||||
if (i==8) s += ' ';
|
||||
s += ' ' + (read!==null?hex(read,2):'??');
|
||||
}
|
||||
@ -667,6 +667,10 @@ export class MemoryView implements ProjectView {
|
||||
if (sym) s += ' ' + sym;
|
||||
return s;
|
||||
}
|
||||
|
||||
readAddress(n : number) {
|
||||
return platform.readAddress(n);
|
||||
}
|
||||
|
||||
getDumpLineAt(line : number) {
|
||||
var d = this.dumplines[line];
|
||||
@ -706,17 +710,27 @@ export class MemoryView implements ProjectView {
|
||||
|
||||
// TODO: use segments list?
|
||||
getMemorySegment(a:number) : string {
|
||||
if (!compparams) return 'unknown';
|
||||
if (a >= compparams.data_start && a < compparams.data_start+compparams.data_size) {
|
||||
if (platform.getSP && a >= platform.getSP() - 15)
|
||||
return 'stack';
|
||||
else
|
||||
return 'data';
|
||||
if (compparams) {
|
||||
if (a >= compparams.data_start && a < compparams.data_start+compparams.data_size) {
|
||||
if (platform.getSP && a >= platform.getSP() - 15)
|
||||
return 'stack';
|
||||
else
|
||||
return 'data';
|
||||
}
|
||||
else if (a >= compparams.code_start && a < compparams.code_start+(compparams.code_size||compparams.rom_size))
|
||||
return 'code';
|
||||
}
|
||||
else if (a >= compparams.code_start && a < compparams.code_start+(compparams.code_size||compparams.rom_size))
|
||||
return 'code';
|
||||
else
|
||||
return 'unknown';
|
||||
var segments = current_project.segments;
|
||||
if (segments) {
|
||||
for (var seg of segments) {
|
||||
if (a >= seg.start && a < seg.start+seg.size) {
|
||||
if (seg.type == 'rom') return 'code';
|
||||
if (seg.type == 'ram') return 'data';
|
||||
if (seg.type == 'io') return 'io';
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
findMemoryWindowLine(a:number) : number {
|
||||
@ -726,6 +740,18 @@ export class MemoryView implements ProjectView {
|
||||
}
|
||||
}
|
||||
|
||||
export class VRAMMemoryView extends MemoryView {
|
||||
readAddress(n : number) {
|
||||
return platform.readVRAMAddress(n);
|
||||
}
|
||||
getMemorySegment(a:number) : string {
|
||||
return 'video';
|
||||
}
|
||||
getDumpLines() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
export class BinaryFileView implements ProjectView {
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user