diff --git a/css/ui.css b/css/ui.css index 45401c04..007f485c 100644 --- a/css/ui.css +++ b/css/ui.css @@ -161,6 +161,7 @@ div.mem_info a.selected { padding-bottom:2px; margin:1px; vertical-align:baseline; + color: #333; } .btn_label { color: #ccc; diff --git a/presets/vcs/examples/bigsprite.a b/presets/vcs/examples/bigsprite.a index b59fa156..9112856e 100644 --- a/presets/vcs/examples/bigsprite.a +++ b/presets/vcs/examples/bigsprite.a @@ -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 diff --git a/presets/vcs/skeleton.ca65 b/presets/vcs/skeleton.ca65 index d5dbd42c..accb19f7 100644 --- a/presets/vcs/skeleton.ca65 +++ b/presets/vcs/skeleton.ca65 @@ -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 diff --git a/presets/vcs/vcs-ca65.h b/presets/vcs/vcs-ca65.h index 85503054..87a4b7d5 100644 --- a/presets/vcs/vcs-ca65.h +++ b/presets/vcs/vcs-ca65.h @@ -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+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 diff --git a/src/common/analysis.ts b/src/common/analysis.ts index 8f01e67a..9c421784 100644 --- a/src/common/analysis.ts +++ b/src/common/analysis.ts @@ -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) { diff --git a/src/ide/pixeleditor.ts b/src/ide/pixeleditor.ts index 49b07517..344c76b9 100644 --- a/src/ide/pixeleditor.ts +++ b/src/ide/pixeleditor.ts @@ -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>(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> (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; + } +} + diff --git a/src/ide/views.ts b/src/ide/views.ts index f5502624..8a05fdb1 100644 --- a/src/ide/views.ts +++ b/src/ide/views.ts @@ -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); } diff --git a/src/worker/lib/vcs/atari2600.cfg b/src/worker/lib/vcs/atari2600.cfg index ed91fa85..0615ba1e 100644 --- a/src/worker/lib/vcs/atari2600.cfg +++ b/src/worker/lib/vcs/atari2600.cfg @@ -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; diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index f887e2bf..e78c21bb 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -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 {