mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-26 07:29:22 +00:00
memory map hover + click; nes presets
This commit is contained in:
parent
4e17913823
commit
ccf5824bb4
@ -409,6 +409,10 @@ div.markdown th {
|
||||
color: #333;
|
||||
background-color:#999;
|
||||
}
|
||||
.segment:hover {
|
||||
border-color: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.segment.segment-ram {
|
||||
background-color:#aaeeaa;
|
||||
}
|
||||
|
@ -54,18 +54,17 @@ HelloMsg:
|
||||
|
||||
; set palette colors
|
||||
SetPalette: subroutine
|
||||
ldy #$00
|
||||
lda #$3f
|
||||
sta PPU_ADDR
|
||||
sty PPU_ADDR
|
||||
ldx #32
|
||||
ldy #$00 ; Y = $00 (also palette index)
|
||||
lda #$3f ; A = $3F
|
||||
sta PPU_ADDR ; $3F?? -> PPU address
|
||||
sty PPU_ADDR ; $3F00 -> PPU address
|
||||
.loop:
|
||||
lda Palette,y
|
||||
sta PPU_DATA
|
||||
iny
|
||||
dex
|
||||
bne .loop
|
||||
rts
|
||||
lda Palette,y ; lookup byte in ROM
|
||||
sta PPU_DATA ; store byte to PPU data
|
||||
iny ; Y = Y + 1
|
||||
cpy #32 ; is Y equal to 32?
|
||||
bne .loop ; not yet, loop
|
||||
rts ; return to caller
|
||||
|
||||
;;;;; COMMON SUBROUTINES
|
||||
|
||||
|
@ -38,31 +38,30 @@ Start:
|
||||
FillVRAM: subroutine
|
||||
txa
|
||||
ldy #$20
|
||||
sty PPU_ADDR
|
||||
sta PPU_ADDR
|
||||
ldy #$10
|
||||
sty PPU_ADDR ; $20?? -> PPU address
|
||||
sta PPU_ADDR ; $2000 -> PPU address
|
||||
ldy #$10 ; set $10 pages ($1000 bytes)
|
||||
.loop:
|
||||
stx PPU_DATA
|
||||
inx
|
||||
bne .loop
|
||||
dey
|
||||
bne .loop
|
||||
rts
|
||||
stx PPU_DATA ; X -> PPU data port
|
||||
inx ; X = X + 1
|
||||
bne .loop ; repeat until 256 bytes
|
||||
dey ; Y = Y - 1
|
||||
bne .loop ; repeat until Y is 0
|
||||
rts ; return to caller
|
||||
|
||||
; set palette colors
|
||||
SetPalette: subroutine
|
||||
ldy #$00
|
||||
lda #$3f
|
||||
sta PPU_ADDR
|
||||
sty PPU_ADDR
|
||||
ldx #32
|
||||
ldy #$00 ; Y = $00 (also palette index)
|
||||
lda #$3f ; A = $3F
|
||||
sta PPU_ADDR ; $3F?? -> PPU address
|
||||
sty PPU_ADDR ; $3F00 -> PPU address
|
||||
.loop:
|
||||
lda Palette,y
|
||||
sta PPU_DATA
|
||||
iny
|
||||
dex
|
||||
bne .loop
|
||||
rts
|
||||
lda Palette,y ; lookup byte in ROM
|
||||
sta PPU_DATA ; store byte to PPU data
|
||||
iny ; Y = Y + 1
|
||||
cpy #32 ; is Y equal to 32?
|
||||
bne .loop ; not yet, loop
|
||||
rts ; return to caller
|
||||
|
||||
|
||||
;;;;; COMMON SUBROUTINES
|
||||
|
@ -21,11 +21,11 @@ void put_str(unsigned int adr, const char *str) {
|
||||
vram_write(str, strlen(str)); // write bytes to PPU
|
||||
}
|
||||
|
||||
static word x_scroll = 0;
|
||||
static byte bldg_height = 8;
|
||||
static byte bldg_width = 8;
|
||||
static byte bldg_char = 1;
|
||||
static byte bldg_attr = 0x55;
|
||||
word x_scroll; // X scroll amount in pixels
|
||||
byte bldg_height; // building height in tiles
|
||||
byte bldg_width; // building width in tiles
|
||||
byte bldg_char; // character to draw
|
||||
byte bldg_attr; // attribute table value
|
||||
|
||||
#define PLAYROWS 24
|
||||
|
||||
@ -34,6 +34,13 @@ word nt2attraddr(word a) {
|
||||
((a >> 4) & 0x38) | ((a >> 2) & 0x07);
|
||||
}
|
||||
|
||||
void new_building() {
|
||||
bldg_height = (rand8() & 7) + 2;
|
||||
bldg_width = (rand8() & 3) * 4 + 4;
|
||||
bldg_char = (rand8() & 15);
|
||||
bldg_attr = rand8();
|
||||
}
|
||||
|
||||
void update_nametable() {
|
||||
word addr;
|
||||
char buf[PLAYROWS];
|
||||
@ -47,6 +54,8 @@ void update_nametable() {
|
||||
// create vertical slice
|
||||
// clear empty space
|
||||
memset(buf, 0, PLAYROWS-bldg_height);
|
||||
// draw a random star
|
||||
buf[rand8() & 31] = '.';
|
||||
// draw roof
|
||||
buf[PLAYROWS-bldg_height-1] = bldg_char & 3;
|
||||
// draw rest of building
|
||||
@ -66,15 +75,15 @@ void update_nametable() {
|
||||
}
|
||||
// generate new building?
|
||||
if (--bldg_width == 0) {
|
||||
bldg_height = (rand8() & 7) + 2;
|
||||
bldg_width = (rand8() & 3) * 4 + 4;
|
||||
bldg_char = (rand8() & 15);
|
||||
bldg_attr = rand8();
|
||||
new_building();
|
||||
}
|
||||
}
|
||||
|
||||
// function to scroll window up and down until end
|
||||
void scroll_demo() {
|
||||
// make 1st building
|
||||
new_building();
|
||||
x_scroll = 0;
|
||||
// infinite loop
|
||||
while (1) {
|
||||
// update nametable every 8 pixels
|
||||
|
34
presets/nes/neslib1.c
Normal file
34
presets/nes/neslib1.c
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
#include "neslib.h"
|
||||
#include <string.h>
|
||||
|
||||
// link the pattern table into CHR ROM
|
||||
//#link "chr_generic.s"
|
||||
|
||||
// function to write a string into the name table
|
||||
// adr = start address in name table
|
||||
// str = pointer to string
|
||||
void put_str(unsigned int adr, const char *str) {
|
||||
vram_adr(adr); // set PPU read/write address
|
||||
vram_write(str, strlen(str)); // write bytes to PPU
|
||||
}
|
||||
|
||||
// main function, run after console reset
|
||||
void main(void) {
|
||||
// set palette colors
|
||||
pal_col(1,0x04);
|
||||
pal_col(2,0x20);
|
||||
pal_col(3,0x30);
|
||||
|
||||
// write text to name table
|
||||
put_str(NTADR_A(2,2),"HELLO, WORLD!");
|
||||
put_str(NTADR_A(2,4),"THIS CODE PRINTS SOME TEXT");
|
||||
put_str(NTADR_A(2,5),"USING ASCII-ENCODED CHARACTER");
|
||||
put_str(NTADR_A(2,6),"SET WITH CAPITAL LETTERS ONLY");
|
||||
|
||||
// enable PPU rendering (turn on screen)
|
||||
ppu_on_all();
|
||||
|
||||
// infinite loop
|
||||
while (1) ;
|
||||
}
|
@ -6,10 +6,12 @@
|
||||
|
||||
#include "neslib.h"
|
||||
|
||||
//#link "tileset1.c"
|
||||
// VRAM buffer module
|
||||
#include "vrambuf.h"
|
||||
//#link "vrambuf.c"
|
||||
|
||||
extern unsigned char palSprites[16];
|
||||
extern unsigned char TILESET[8*256];
|
||||
// link the pattern table into CHR ROM
|
||||
//#link "chr_generic.s"
|
||||
|
||||
#define COLS 32
|
||||
#define ROWS 27
|
||||
@ -31,48 +33,13 @@ byte getchar(byte x, byte y) {
|
||||
return rd + 0x20;
|
||||
}
|
||||
|
||||
// VRAM UPDATE BUFFER
|
||||
|
||||
byte updbuf[64];
|
||||
byte updptr = 0;
|
||||
|
||||
void cendbuf() {
|
||||
updbuf[updptr] = NT_UPD_EOF;
|
||||
}
|
||||
|
||||
void cflushnow() {
|
||||
cendbuf();
|
||||
waitvsync();
|
||||
flush_vram_update(updbuf);
|
||||
updptr = 0;
|
||||
cendbuf();
|
||||
vram_adr(0x0);
|
||||
}
|
||||
|
||||
void vdelay(byte count) {
|
||||
while (count--) cflushnow();
|
||||
}
|
||||
|
||||
void cputcxy(byte x, byte y, char ch) {
|
||||
word addr = NTADR_A(x,y);
|
||||
if (updptr >= 60) cflushnow();
|
||||
updbuf[updptr++] = addr >> 8;
|
||||
updbuf[updptr++] = addr & 0xff;
|
||||
updbuf[updptr++] = ch - 0x20;
|
||||
cendbuf();
|
||||
putbytes(NTADR_A(x,y), &ch, 1);
|
||||
}
|
||||
|
||||
void cputsxy(byte x, byte y, char* str) {
|
||||
word addr = NTADR_A(x,y);
|
||||
byte len = strlen(str);
|
||||
if (updptr >= 60 - len) cflushnow();
|
||||
updbuf[updptr++] = (addr >> 8) | NT_UPD_HORZ;
|
||||
updbuf[updptr++] = addr & 0xff;
|
||||
updbuf[updptr++] = len;
|
||||
while (len--) {
|
||||
updbuf[updptr++] = *str++ - 0x20;
|
||||
}
|
||||
cendbuf();
|
||||
void cputsxy(byte x, byte y, const char* str) {
|
||||
putbytes(NTADR_A(x,y), str, strlen(str));
|
||||
}
|
||||
|
||||
void clrscr() {
|
||||
@ -133,7 +100,7 @@ void draw_playfield() {
|
||||
cputcxy(9,1,players[0].score+'0');
|
||||
cputcxy(28,1,players[1].score+'0');
|
||||
if (attract) {
|
||||
cputsxy(5,ROWS-1,"ATTRACT MODE - PRESS 1");
|
||||
cputsxy(3,ROWS-1,"ATTRACT MODE - PRESS ENTER");
|
||||
} else {
|
||||
cputsxy(1,1,"PLYR1:");
|
||||
cputsxy(20,1,"PLYR2:");
|
||||
@ -229,7 +196,8 @@ void flash_colliders() {
|
||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, i/2);
|
||||
if (players[0].collided) players[0].head_attr ^= 0x80;
|
||||
if (players[1].collided) players[1].head_attr ^= 0x80;
|
||||
vdelay(2);
|
||||
cflushnow();
|
||||
cflushnow();
|
||||
draw_player(&players[0]);
|
||||
draw_player(&players[1]);
|
||||
}
|
||||
@ -240,7 +208,7 @@ void make_move() {
|
||||
byte i;
|
||||
for (i=0; i<frames_per_move; i++) {
|
||||
human_control(&players[0]);
|
||||
vdelay(1);
|
||||
cflushnow();
|
||||
}
|
||||
ai_control(&players[0]);
|
||||
ai_control(&players[1]);
|
||||
@ -254,12 +222,13 @@ void declare_winner(byte winner) {
|
||||
clrscr();
|
||||
for (i=0; i<ROWS/2-3; i++) {
|
||||
draw_box(i,i,COLS-1-i,ROWS-1-i,BOX_CHARS);
|
||||
vdelay(1);
|
||||
cflushnow();
|
||||
}
|
||||
cputsxy(12,10,"WINNER:");
|
||||
cputsxy(12,13,"PLAYER ");
|
||||
cputcxy(12+7, 13, '1'+winner);
|
||||
vdelay(75);
|
||||
cflushnow();
|
||||
delay(75);
|
||||
gameover = 1;
|
||||
}
|
||||
|
||||
@ -338,9 +307,9 @@ void play_game() {
|
||||
}
|
||||
|
||||
void main() {
|
||||
vram_adr(0x0);
|
||||
vram_write((unsigned char*)TILESET, sizeof(TILESET));
|
||||
joy_install (joy_static_stddrv);
|
||||
cendbuf();
|
||||
set_vram_update(updbuf);
|
||||
while (1) {
|
||||
attract = 1;
|
||||
play_game();
|
||||
|
@ -28,7 +28,7 @@ void cflushnow(void) {
|
||||
|
||||
// add multiple characters to update buffer
|
||||
// using horizontal increment
|
||||
void putbytes(word addr, char* str, byte len) {
|
||||
void putbytes(word addr, const char* str, byte len) {
|
||||
if (updptr >= VBUFSIZE-4-len) cflushnow();
|
||||
updbuf[updptr++] = (addr >> 8) ^ NT_UPD_HORZ;
|
||||
updbuf[updptr++] = addr & 0xff;
|
||||
|
@ -33,6 +33,6 @@ void cflushnow(void);
|
||||
|
||||
// add multiple characters to update buffer
|
||||
// using horizontal increment
|
||||
void putbytes(word addr, char* str, byte len);
|
||||
void putbytes(word addr, const char* str, byte len);
|
||||
|
||||
#endif // vrambuf.h
|
||||
|
59
presets/nes/vrambuffer.c
Normal file
59
presets/nes/vrambuffer.c
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
#include "neslib.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// VRAM buffer module
|
||||
#include "vrambuf.h"
|
||||
//#link "vrambuf.c"
|
||||
|
||||
// link the pattern table into CHR ROM
|
||||
//#link "chr_generic.s"
|
||||
|
||||
// function to scroll window up and down until end
|
||||
void scroll_demo() {
|
||||
int x = 0; // x scroll position
|
||||
int y = 0; // y scroll position
|
||||
int dy = 1; // y scroll direction
|
||||
// 32-character array for string-building
|
||||
char str[32];
|
||||
// clear string array
|
||||
memset(str, 0, sizeof(str));
|
||||
// infinite loop
|
||||
while (1) {
|
||||
// write message to string array
|
||||
sprintf(str, "%6x %6d", y, y);
|
||||
// write string array into VRAM buffer
|
||||
putbytes(NTADR_A(2,y%30), str, 32);
|
||||
// wait for next frame
|
||||
// and flush VRAM buffer
|
||||
cflushnow();
|
||||
// set scroll register
|
||||
scroll(x, y);
|
||||
// update y variable
|
||||
y += dy;
|
||||
// change direction when hitting either edge of scroll area
|
||||
if (y >= 479) dy = -1;
|
||||
if (y == 0) dy = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// main function, run after console reset
|
||||
void main(void) {
|
||||
// set palette colors
|
||||
pal_col(1,0x04);
|
||||
pal_col(2,0x20);
|
||||
pal_col(3,0x30);
|
||||
|
||||
// clear vram buffer
|
||||
cclearbuf();
|
||||
|
||||
// set NMI handler
|
||||
set_vram_update(updbuf);
|
||||
|
||||
// enable PPU rendering (turn on screen)
|
||||
ppu_on_all();
|
||||
|
||||
// scroll window back and forth
|
||||
scroll_demo();
|
||||
}
|
@ -16,14 +16,15 @@ const JSNES_PRESETS = [
|
||||
{id:'ex4.asm', name:'Controller Demo (ASM)'},
|
||||
{id:'neslib1.c', name:'Text'},
|
||||
{id:'scroll.c', name:'Scrolling'},
|
||||
{id:'statusbar.c', name:'Status Bar'},
|
||||
{id:'horizmask.c', name:'Horizontal Scrolling'},
|
||||
{id:'vrambuffer.c', name:'VRAM Buffer'},
|
||||
{id:'sprites.c', name:'Sprites'},
|
||||
{id:'metasprites.c', name:'Metasprites'},
|
||||
{id:'flicker.c', name:'Flickering Sprites'},
|
||||
{id:'metacursor.c', name:'Controllers'},
|
||||
{id:'metatrigger.c', name:'Trigger Mode + Vbright'},
|
||||
{id:'neslib5.c', name:'RLE Unpack'},
|
||||
{id:'statusbar.c', name:'Split Status Bar'},
|
||||
{id:'horizmask.c', name:'Horizontal Scrolling'},
|
||||
{id:'music.c', name:'Music Player'},
|
||||
{id:'siegegame.c', name:'Siege Game'},
|
||||
{id:'shoot2.c', name:'Solarian Game'},
|
||||
|
@ -32,7 +32,7 @@ var toolbar = $("#controls_top");
|
||||
|
||||
export var current_project : CodeProject; // current CodeProject object
|
||||
|
||||
var projectWindows : ProjectWindows; // window manager
|
||||
export var projectWindows : ProjectWindows; // window manager
|
||||
|
||||
var stateRecorder : StateRecorderImpl;
|
||||
|
||||
|
14
src/views.ts
14
src/views.ts
@ -7,7 +7,7 @@ import { SourceFile, WorkerError, Segment } from "./workertypes";
|
||||
import { Platform, EmuState } from "./baseplatform";
|
||||
import { hex, lpad, rpad } from "./util";
|
||||
import { CodeAnalyzer } from "./analysis";
|
||||
import { platform, platform_id, compparams, current_project, lastDebugState } from "./ui";
|
||||
import { platform, platform_id, compparams, current_project, lastDebugState, projectWindows } from "./ui";
|
||||
|
||||
export interface ProjectView {
|
||||
createDiv(parent:HTMLElement, text:string) : HTMLElement;
|
||||
@ -608,7 +608,11 @@ export class MemoryView implements ProjectView {
|
||||
$(parent).append(this.memorylist.container);
|
||||
this.tick();
|
||||
if (compparams && this.dumplines)
|
||||
this.memorylist.scrollToItem(this.findMemoryWindowLine(compparams.data_start));
|
||||
this.scrollToAddress(compparams.data_start);
|
||||
}
|
||||
|
||||
scrollToAddress(addr : number) {
|
||||
this.memorylist.scrollToItem(this.findMemoryWindowLine(addr));
|
||||
}
|
||||
|
||||
refresh() {
|
||||
@ -694,6 +698,7 @@ export class MemoryView implements ProjectView {
|
||||
return this.dumplines;
|
||||
}
|
||||
|
||||
// TODO: use segments list?
|
||||
getMemorySegment(a:number) : string {
|
||||
if (!compparams) return 'unknown';
|
||||
if (a >= compparams.data_start && a < compparams.data_start+compparams.data_size) {
|
||||
@ -805,6 +810,11 @@ export class MemoryMapView implements ProjectView {
|
||||
var row = $('<div class="row"/>').append(offset, segdiv);
|
||||
var container = $('<div class="container"/>').append(row);
|
||||
this.maindiv.append(container);
|
||||
segdiv.click(() => {
|
||||
var memview = projectWindows.createOrShow('#memory') as MemoryView;
|
||||
memview.scrollToAddress(seg.start);
|
||||
// TODO: this doesn't update nav bar
|
||||
});
|
||||
}
|
||||
|
||||
refresh() {
|
||||
|
@ -25,11 +25,11 @@ export class ProjectWindows {
|
||||
}
|
||||
// TODO: delete windows ever?
|
||||
|
||||
setCreateFunc(id:string, createfn:WindowCreateFunction) {
|
||||
setCreateFunc(id:string, createfn:WindowCreateFunction) : void {
|
||||
this.id2createfn[id] = createfn;
|
||||
}
|
||||
|
||||
createOrShow(id:string) {
|
||||
createOrShow(id:string) : ProjectView {
|
||||
var wnd = this.id2window[id];
|
||||
if (!wnd) {
|
||||
wnd = this.id2window[id] = this.id2createfn[id](id);
|
||||
@ -52,27 +52,27 @@ export class ProjectWindows {
|
||||
return wnd;
|
||||
}
|
||||
|
||||
put(id:string, window:ProjectView) {
|
||||
put(id:string, window:ProjectView) : void {
|
||||
this.id2window[id] = window;
|
||||
}
|
||||
|
||||
refresh(moveCursor:boolean) {
|
||||
refresh(moveCursor:boolean) : void {
|
||||
// refresh current window
|
||||
if (this.activewnd && this.activewnd.refresh)
|
||||
this.activewnd.refresh(moveCursor);
|
||||
}
|
||||
|
||||
tick() {
|
||||
tick() : void {
|
||||
if (this.activewnd && this.activewnd.tick)
|
||||
this.activewnd.tick();
|
||||
}
|
||||
|
||||
setErrors(errors:WorkerError[]) {
|
||||
setErrors(errors:WorkerError[]) : void {
|
||||
this.lasterrors = errors;
|
||||
this.refreshErrors();
|
||||
}
|
||||
|
||||
refreshErrors() {
|
||||
refreshErrors() : void {
|
||||
if (this.activewnd && this.activewnd.markErrors) {
|
||||
if (this.lasterrors && this.lasterrors.length)
|
||||
this.activewnd.markErrors(this.lasterrors);
|
||||
|
Loading…
Reference in New Issue
Block a user