mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-04-09 06:37:07 +00:00
pixel editor: reindex for vcs playfields, fixed ca65 stuff
This commit is contained in:
parent
64fcbdc9d5
commit
c5ccd4ff48
@ -161,6 +161,7 @@ div.mem_info a.selected {
|
||||
padding-bottom:2px;
|
||||
margin:1px;
|
||||
vertical-align:baseline;
|
||||
color: #333;
|
||||
}
|
||||
.btn_label {
|
||||
color: #ccc;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user