1
0
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:
Steven Hugg 2019-02-26 10:56:51 -05:00
parent 4e17913823
commit ccf5824bb4
13 changed files with 186 additions and 102 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
View 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) ;
}

View File

@ -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();

View File

@ -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;

View File

@ -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
View 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();
}

View File

@ -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'},

View File

@ -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;

View File

@ -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() {

View File

@ -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);