Howdy Doody PCOPY (and dual scrolling in opposite directions) test

Started by CharlieJV, Jul 09, 2023, 02:39 AM

Previous topic - Next topic

CharlieJV


CharlieJV

The original version of the program was meant to give PCOPY a good sanity test.

This version has less PCOPYing going and a bit less code, and is noticeably faster:


johnno56

May your journey be free of incident.  Live long and prosper.

ZXDunny

What accounts for the speed up in the second version? Less PCOPYing?

CharlieJV

Quote from: ZXDunny on Jul 09, 2023, 10:47 AMWhat accounts for the speed up in the second version? Less PCOPYing?

Yup.  PCOPY is a bit laborious at the moment.  Every pixel of the screen is a cell in an array, and PCOPY copies every cell from one array to the other.  So takes a bit of time looping through all of the arrays for every PCOPY.

I haven't yet figured out how to get javascript to copy a whole array to a whole array in one sweep.

Tomaaz

Quote from: CharlieJV on Jul 09, 2023, 01:40 PMI haven't yet figured out how to get javascript to copy a whole array to a whole array in one sweep.

second_array = [].concat(first_array)

ZXDunny

Keep forgetting it's JS - I'm used to just grabbing memory and dumping it from one place to another :)

But then mine isn't anything like as portable as yours!

CharlieJV

Quote from: Tomaaz on Jul 09, 2023, 03:05 PM
Quote from: CharlieJV on Jul 09, 2023, 01:40 PMI haven't yet figured out how to get javascript to copy a whole array to a whole array in one sweep.

second_array = [].concat(first_array)


I've tried multiple approaches to copying one array to another, but had not tried that one.  Thanks!

Unfortunately, none work.  For some reason, any approach of copying page "x" array to the display_data array, other than a cell by cell copy from the page "x" array, causes the BASIC console window to stop displaying output.

For anybody who actually enjoys staring into javascript's eyeballs, this does work A-1, just a bit slow (although slightly faster than the version in the OP because of some mods I did this morning):

    function Pcopy(x1,y1,x2,y2,s,d) {
        var srcdata;
        if (x1==undefined || x1<0) {x1=0;}
        if (y1==undefined || y1<0) {y1=0;}
        if (x2==undefined || x2>display.width-1) {x2=display.width-1;}
        if (y2==undefined || y2>display.height-1) {y2=display.height-1;}
        switch(s) {
        case 0:
          srcdata = display_data; break;
        case 1:
          if (page1==undefined) {alert("Page 1 is undefined");}
          srcdata = page1; break;
        case 2:
          if (page2==undefined) {alert("Page 2 is undefined");}
          srcdata = page2; break;
        default:
          alert(s + " is an invalid source page for PCOPY."); return;
        }
        switch(d) {
          case 0:
            for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                      display_data[x+y*display.width] = srcdata[x+y*display.width];
            }}
            break;
          case 1:
            if (page1==undefined) {page1=[...srcdata];}
            else if (x1==0 && y1==0 && x2==display.width-1 && y2==display.height - 1) {page1=[...srcdata];}
            else {for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                      page1[x+y*display.width] = srcdata[x+y*display.width];
            }}}
            break;
          case 2:
            if (page2==undefined) {page2=[...srcdata];}
            else if (x1==0 && y1==0 && x2==display.width-1 && y2==display.height - 1) {page2=[...srcdata];}
            else {for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                        page2[x+y*display.width] = srcdata[x+y*display.width];
            }}}
            break;
        default:
          alert(d + " is an invalid destination page for PCOPY."); return;
        }
    }

Tomaaz

You're making several shallow copies of arrays and from this piece of code is very difficult to decide if that's what you need.

ZXDunny

Instead of calculating an offset, can you not just do something like (I don't code JS):

for i = 0 to width*height-1: 
   dest[i] = src[i]:
next i

Which I think would probably be at least a little faster. I mean, all three pages have to be the same size, don't they?

Tomaaz

dest = [].concat(src)

should do the same thing, assuming a hard copy of src is needed .

CharlieJV

Quote from: ZXDunny on Jul 09, 2023, 05:08 PMInstead of calculating an offset, can you not just do something like (I don't code JS):

for i = 0 to width*height-1: 
  dest[i] = src[i]:
next i

Which I think would probably be at least a little faster. I mean, all three pages have to be the same size, don't they?

That would be A-1 for
PCOPY source_page, destination_page
, but that wouldn't work for
PCOPY (x1,y1) - (x2,y2) source_page, destination_page

I think.  Not quite sure what your're suggesting.

CharlieJV

Quote from: Tomaaz on Jul 09, 2023, 04:52 PMYou're making several shallow copies of arrays and from this piece of code is very difficult to decide if that's what you need.

With about 4,000 lines of code, I'm not sure what bits I'd need to pull out to help with context. So...

I'm not sure the juice is worth the squeeze, so what I have currently working will be good enough.

Thanks for the eyeballs!


ZXDunny

Quote from: CharlieJV on Jul 09, 2023, 05:31 PMThat would be A-1 for
PCOPY source_page, destination_page
, but that wouldn't work for
PCOPY (x1,y1) - (x2,y2) source_page, destination_page

I think.  Not quite sure what your're suggesting.

Ah yes, the rectangle argument. Still, would be a pretty good speed up for the non-rect case.

CharlieJV

Quote from: ZXDunny on Jul 09, 2023, 06:35 PM
Quote from: CharlieJV on Jul 09, 2023, 05:31 PMThat would be A-1 for
PCOPY source_page, destination_page
, but that wouldn't work for
PCOPY (x1,y1) - (x2,y2) source_page, destination_page

I think.  Not quite sure what your're suggesting.

Ah yes, the rectangle argument. Still, would be a pretty good speed up for the non-rect case.

That's what I did this morning for two of the three select cases:

switch(d) {
          case 0:
            for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                      display_data[x+y*display.width] = srcdata[x+y*display.width];
            }}
            break;
          case 1:
            if (page1==undefined) {page1=[...srcdata];}
            else if (x1==0 && y1==0 && x2==display.width-1 && y2==display.height - 1) {page1=[...srcdata];}
            else {for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                      page1[x+y*display.width] = srcdata[x+y*display.width];
            }}}
            break;
          case 2:
            if (page2==undefined) {page2=[...srcdata];}
            else if (x1==0 && y1==0 && x2==display.width-1 && y2==display.height - 1) {page2=[...srcdata];}
            else {for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                        page2[x+y*display.width] = srcdata[x+y*display.width];
            }}}
            break;

Like I was saying, that did make a slight improvement (noticeably faster, but nowhere near as fast as the version in my post right after the OP.

So I've got those IF conditions in there to do things one way if entire arrays (for all screen pixels) are involved versus just a subset area.

I just applied the same thing to the first case, and it isn't making any improvement.

The modified code for case 0:

case 0:
            if (x1==0 && y1==0 && x2==display.width-1 && y2==display.height - 1) {
                 for (var i = 0; i < display.width * display.height; i++) {
                   display_data[i] = srcdata[i];}}
            else {for (var y = y1; y < y2+1; y++) {
                    for (var x = x1; x < x2+1; x++) {
                      display_data[x+y*display.width] = srcdata[x+y*display.width];




Cases 1 and 2 are improved because I can assign to the "page X" arrays a whole array (so whole array copied to other array in one step: pageX=[...srcdata] works A-1.

If I could do that for case 0, then there would be a slight performance boost.  However, there is something about the display_data array that causes display_data=[...srcdata] to bork output to the screen.

All of that to say, single big loop versus nested loops (with index calculations in the nested loop) aren't making any difference that I can tell (because addition and multiplication are quick.)