pixel editor: reindex for vcs playfields, fixed ca65 stuff

This commit is contained in:
Steven Hugg 2021-03-28 19:39:41 -05:00
parent 64fcbdc9d5
commit c5ccd4ff48
9 changed files with 125 additions and 15 deletions

View File

@ -161,6 +161,7 @@ div.mem_info a.selected {
padding-bottom:2px;
margin:1px;
vertical-align:baseline;
color: #333;
}
.btn_label {
color: #ccc;

View File

@ -94,6 +94,7 @@ BigLoop
; Bitmap data, six columns
align $100 ; ensure we start on a page boundary
;;{w:8,h:65,count:6,brev:1,flip:1};;
Bitmap0
hex 00
hex 00000000000000000000000000000000
@ -130,6 +131,7 @@ Bitmap5
hex f800e01804040402020101010111e192
hex dc700000000000000000000080808000
hex 00000000000000000000000000000000
;;
; Epilogue
org $fffc

View File

@ -4,7 +4,6 @@
.zeropage
Temp: .byte 0
.segment "CODE"
Reset:
@ -26,7 +25,6 @@ NextFrame:
.segment "VECTORS"
.word Reset
.word Reset
.word Reset
VecNMI: .word Reset
VecReset: .word Reset
VecBRK: .word Reset

View File

@ -89,8 +89,8 @@ TIM1024T := $0297
; Uses illegal opcode (DASM 2.20.01 onwards).
.macro SLEEP cycles
.if cycles < 2
.error "MACRO ERROR: 'SLEEP': Duration must be > 1"
.if cycles < 0 || cycles = 1
.error "MACRO ERROR: 'SLEEP': Duration must be >= 2"
.endif
.if cycles & 1
.ifndef NO_ILLEGAL_OPCODES
@ -180,6 +180,26 @@ CLEAR_STACK: dex
bne CLEAR_STACK ; SP=$FF, X = A = Y = 0
.endmacro
;-------------------------------------------------------
; SET_POINTER
; Original author: Manuel Rotschkar
;
; Sets a 2 byte RAM pointer to an absolute address.
;
; Usage: SET_POINTER pointer, address
; Example: SET_POINTER SpritePTR, SpriteData
;
; Note: Alters the accumulator, NZ flags
; IN 1: 2 byte RAM location reserved for pointer
; IN 2: absolute address
.macro SET_POINTER ptr, addr
lda #<addr
sta ptr
lda #>addr
sta ptr+1
.endmacro
; assume NTSC unless PAL defined
.ifndef PAL
PAL = 0
@ -188,8 +208,10 @@ PAL = 0
; 192 visible scanlines for NTSC, 228 for PAL
.if PAL
SCANLINES = 228
LINESD12 = 19
.else
SCANLINES = 192
LINESD12 = 16
.endif
; start of frame -- vsync and set back porch timer
@ -230,3 +252,17 @@ SCANLINES = 192
.macro FRAME_END
TIMER_WAIT
.endmacro
;-----------------------------------------------------------
; SLEEPR - sleep macro that uses JSR/RTS for 12 cycle delays
; Requires a lone RTS instruction with the label "Return"
; (note: may fool 8bitworkshop's Anaylze CPU Timing feature)
.macro SLEEPR cycles
.if cycles >= 14 || cycles = 12
jsr Return
SLEEPR (cycles-12)
.else
SLEEP cycles
.endif
.endmacro

View File

@ -142,6 +142,7 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
}
break;
case 0x20: // JSR
// TODO: handle bare RTS case
this.traceInstructions(addr, minclocks, maxclocks, addr, constraints);
var result = this.jsrresult[addr];
if (result) {

View File

@ -37,6 +37,7 @@ export type PixelEditorImageFormat = {
sl?:number
pofs?:number
remap?:number[]
reindex?:number[]
brev?:boolean
flip?:boolean
destfmt?:PixelEditorImageFormat
@ -62,6 +63,7 @@ type PixelEditorMessage = {
/////////////////
// 0xabcd, #$abcd, 5'010101, 0b010101, etc
var pixel_re = /([0#]?)([x$%]|\d'h)([0-9a-f]+)(?:[;].*)?|(\d'b|0b)([01]+)/gim;
@ -143,6 +145,13 @@ function remapBits(x:number, arr:number[]) : number {
return y;
}
// for VCS playfields
// ;;{w:20,h:10,flip:1,reindex:[4,5,6,7,15,14,13,12,11,10,9,8,16,17,18,19]};;
function reindexMask(x:number, inds:number[]) : [number, number] {
var i = inds[x % inds.length];
return [i >> 3, i & 7];
}
function convertWordsToImages(words:UintArray, fmt:PixelEditorImageFormat) : Uint8Array[] {
var width = fmt.w;
var height = fmt.h;
@ -164,13 +173,14 @@ function convertWordsToImages(words:UintArray, fmt:PixelEditorImageFormat) : Uin
for (var x=0; x<width; x++) {
var color = 0;
var ofs = remapBits(ofs0, fmt.remap);
if (fmt.reindex) { [ofs, shift] = reindexMask(x, fmt.reindex); ofs += ofs0; }
for (var p=0; p<nplanes; p++) {
var byte = words[ofs + p*pofs + skip];
color |= ((fmt.brev ? byte>>(bitsperword-shift-bpp) : byte>>shift) & mask) << (p*bpp);
}
imgdata.push(color);
shift += bpp;
if (shift >= bitsperword) {
if (shift >= bitsperword && !fmt.reindex) {
ofs0 += 1;
shift = 0;
}
@ -210,12 +220,13 @@ function convertImagesToWords(images:Uint8Array[], fmt:PixelEditorImageFormat) :
for (var x=0; x<width; x++) {
var color = imgdata[i++];
var ofs = remapBits(ofs0, fmt.remap);
if (fmt.reindex) { [ofs, shift] = reindexMask(x, fmt.reindex); ofs += ofs0; }
for (var p=0; p<nplanes; p++) {
var c = (color >> (p*bpp)) & mask;
words[ofs + p*pofs + skip] |= (fmt.brev ? (c << (bitsperword-shift-bpp)) : (c << shift));
}
shift += bpp;
if (shift >= bitsperword) {
if (shift >= bitsperword && !fmt.reindex) {
ofs0 += 1;
shift = 0;
}
@ -600,6 +611,7 @@ function dedupPalette(cols : UintArray) : Uint32Array {
}
return res;
}
export class PaletteFormatToRGB extends PixNode {
words : UintArray;
@ -851,8 +863,13 @@ export class CharmapEditor extends PixNode {
var im = new PixEditor();
im.createWith(viewer);
im.updateImage();
im.canvas.style.width = (viewer.width*xscale)+'px'; // TODO
im.canvas.style.height = (viewer.height*yscale)+'px'; // TODO
var w = viewer.width * xscale;
var h = viewer.height * yscale;
while (w > 500 || h > 500) {
w /= 2; h /= 2;
}
im.canvas.style.width = w+'px'; // TODO
im.canvas.style.height = h+'px'; // TODO
im.makeEditable(this, aeditor, this.left.palette);
return im;
}
@ -1103,3 +1120,57 @@ class PixEditor extends Viewer {
}
}
// TODO: not yet used
abstract class TwoWayPixelConverter {
w : number;
h : number;
words : Uint8Array;
bitoffsets : Uint32Array;
coloffsets : Uint32Array;
constructor(width: number, height: number, bpp: number, colpp: number) {
this.w = width;
this.h = height;
this.words = new Uint8Array(width * height);
this.bitoffsets = new Uint32Array(width * height);
this.coloffsets = new Uint32Array(width * height);
}
setPixel(x:number, y:number, col:number, bitofs:number, colofs:number) {
var ofs = x + y * this.w;
this.words[ofs] = col;
this.bitoffsets[ofs] = bitofs;
this.coloffsets[ofs] = colofs;
}
abstract wordsToImage(words: UintArray) : Uint8Array[];
abstract imageToWords(image: Uint8Array) : UintArray;
}
export class TwoWayMapper extends PixNode {
pc: TwoWayPixelConverter;
constructor(pc: TwoWayPixelConverter) {
super();
this.pc = pc;
}
updateLeft() {
//if (equalNestedArrays(this.images, this.right.images)) return false;
this.images = this.right.images;
this.words = this.pc.imageToWords(this.images[0]);
return true;
}
updateRight() {
if (equalArrays(this.words, this.left.words)) return false;
// convert each word array to images
this.words = this.left.words;
this.images = this.pc.wordsToImage(this.words);
return true;
}
}

View File

@ -301,7 +301,7 @@ export class SourceEditor implements ProjectView {
} else if (platform.getOpcodeMetadata) {
var opcode = parseInt(info.insns.split(" ")[0], 16);
var meta = platform.getOpcodeMetadata(opcode, info.offset);
if (meta) {
if (meta && meta.minCycles) {
var clockstr = meta.minCycles+"";
this.setGutter("gutter-clock", info.line-1, clockstr);
}

View File

@ -9,8 +9,8 @@ MEMORY {
}
SEGMENTS {
RODATA: load=ROM, type=ro, align = $100;
CODE: load=ROM, type=ro, define=yes;
RODATA: load=ROM, type=ro, align=$100;
CODE: load=ROM, type=ro, align=$100, define=yes;
DATA: load=ROM, run=RAM, type=rw, define=yes;
BSS: load=RAM, type=bss, define=yes;
VECTORS: load=ROM, type=ro, start=$FFFA;

View File

@ -962,7 +962,8 @@ function parseCA65Listing(code, symbols, params, dbg) {
lines.push({
line:linenum,
offset:offset + segofs,
insns:insns
insns:insns,
iscode:true // TODO: can't really tell unless we parse it
});
}
} else {