A FULL-SCREEN PIXEL EDITOR

by Barry Christie

Use this pixel editor to edit full-screen images created in modes 13 and 15, or use it as a powerful drawing tool to create your own pictures.

Although the Sprite Editor supplied on the Welcome disc provides pixel editing facilities, the accompanying program offers a number of advantages. The Pixel Editor presented here gives the user a much larger display area in edit mode, and provides three levels of zoom to further improve flexibility. It can also display the whole screen at the touch of a button, and allows the user to move around the screen at great speed. It also provides a flood fill option, and allows the user to "pick up" colours from an existing picture, rather than insisting that they be selected each time from the cumbersome palette display.

USING THE PIXEL EDITOR

First of all you should type in the accompanying program, and save it away. When it is run it will begin by checking whether you have sufficient configured screen RAM. The program uses dual screens to give fast switching between edit and full display modes, and will therefore need 160K of RAM if used in mode 13, and 320K for mode 15. Use *CON.SCR.20 followed by Ctrl-Break to allocate 160K, or *CON.SCR.40 to allocate 320K. If you are using a 305 it is just possible to get 320K of screen RAM, but you will need to configure all other options to zero, except for sprite space, which should be kept at 1. Users of other machines will also need to have at least 1 unit of sprite space.

Once the program initialises you will be presented with the option screen. This offers four possibilities: star commands, screen save, screen load or edit mode. To get straight into edit mode, click on "EDIT", and reply to the prompt to select a mode. Again, if there is insufficient RAM, you will be informed. If all is well you will find yourself in the editing screen.

THE EDITING SCREEN

The editing screen is split vertically into two sectors. The left-most two inches or so of the screen constitute the control area, while the rest is occupied by the editing area. All functions in the control area are activated by the middle mouse button (the menu button), while in the main editing area, all three buttons are used as follows:
selectDraw in current colour
menuPick up new colour
adjustFlood fill in current colour

The currently selected colour is displayed above the colour palette in the control area. Using the menu button on the displayed palette in the control area will pick up a new colour. Pressing the menu button in the editing area will also pick up the colour currently under the pointer. The flood fill is a very useful option, though you should beware of "leaks" in any area to be filled. To make sure that it is not used by accident it requires a double click of the adjust button.

The control area itself is split into three unequal sections. At the top appears a true size image of the area being edited. If you click the menu button here, you will switch to a display of the whole screen with a window marker. Moving the mouse allows you to move the window to any part of the screen to redefine the editing area. A second click of the menu button will take you back to editing mode with the new area selected.

Using the menu button on the central palette portion of the control area permits the selection of a new drawing colour. Finally, in the bottom left hand corner of the screen there is an eight-point scroller. Press the menu button on the appropriate point to scroll the drawing area in any one of eight directions; or in the centre to cycle through the three zoom options. Additionally there are two further options, but these are both initiated from the keyboard. Pressing the space bar will take you back to the option screen, while pressing Ctrl-Home will offer a screen clear. Finally, to quit the program, press Ctrl-Escape.

10 REM >PixlEdit9
20 REM Program Pixel Editor
30 REM Requires 160-320K of scn RAM
40 REM and 8K of sprite RAM
50 REM Version A 0.9
60 REM Author Barry Christie
70 REM RISC User March 1988
80 REM Program Subject to copyright
90 REM:
100 MODE 12:DIM B% &20
110 noerror=TRUE:validmode=FALSE
120 IF FNscrnsize<160 THEN PROCmessage:END
130 mx=640:editx=0:my=512:edity=0
140 ON ERROR PROCerror
150 WHILE noerror
160 MODE 12:PROCoption
170 ENDWHILE
180 END
190 :
200 DEF PROCoption
210 PROCoptionscreen
220 MOUSE TO mx,my:*POINTER
230 REPEAT
240 REPEAT:MOUSE mx,my,mb:UNTIL mb<>0
250 chosen=mx DIV 320:areax=mx-chosen*320:areay=(my+128) DIV 160
260 areachosen=areax>16 AND areax<304 AND areay=1:CLS
270 IF areachosen THEN
280 ON:*FX15
290 CASE chosen OF
300 WHEN 0:PROCstarcommand
310 WHEN 1:PROCloadpicture
320 WHEN 2:PROCsavepicture
330 WHEN 3:IF validmode THEN PROCeditpicture ELSE PROCsetup:PROCeditpicture
340 ENDCASE:OFF
350 ENDIF
360 UNTIL areachosen
370 ENDPROC
380 :
390 DEF PROCstarcommand
400 INPUT "Please enter <STAR> command ... *"command$
410 PRINT:OSCLI(command$):PROCcontinue
420 ENDPROC
430 :
440 DEF PROCloadpicture
450 INPUT "Enter <filename> of picture to LOAD ... "filename$
460 OSCLI("SCREENLOAD "+filename$):validmode=MODE
470 PROCvalidatemode
480 ENDPROC
490 :
500 DEF PROCvalidatemode
510 CASE validmode OF
520 WHEN 13:PROCassemble(320,4,&14000)
530 WHEN 15:PROCassemble(640,2,&28000)
540 OTHERWISE:validmode=FALSE
550 ENDCASE
560 ENDPROC
570 :
580 DEF PROCsavepicture
590 INPUT "Enter <filename> of picture to SAVE ... "filename$:MODE validmode
600 PROCdriversdisplay(2,2):OSCLI("SCREENSAVE "+filename$)
610 PROCdriversdisplay(1,1)
620 ENDPROC
630 :
640 DEF PROCeditpicture
650 IF validmode THEN
660 PROCeditorscreen
670 REPEAT
680 MOUSE mx,my,mb
690 IF mx>260 THEN
700 CASE mb OF
710 WHEN 1:PROCfillingfunc
720 WHEN 2:PROCscrncolfunc
730 WHEN 4:PROCdrawingfunc
740 ENDCASE
750 ENDIF
760 IF mx<255 AND mb=2 THEN
770 CASE TRUE OF
780 WHEN my<255:PROCcontrolfunc
790 WHEN my>255 AND my<704:PROCmenucolfunc
800 WHEN my>764:PROCeditingfunc
810 ENDCASE
820 ENDIF
830 IF INKEY(-2) AND INKEY(-63) THEN PROCwipeoutfunc
840 UNTIL INKEY(-99)
850 ENDIF:ENDPROC
860 :
870 DEF PROCfillingfunc
880 REPEAT:MOUSE mx,my,mb:UNTIL mb=0
890 TIME=0:REPEAT UNTIL TIME>50
900 MOUSE mx,my,mb:IF mb<>1 THEN ENDPROC
910 GCOL POINT(mx,my)+128 TINT (TINT(mx,my)):GCOL gcol TINT tint
920 PROCpictureplot(133):GCOL 128 TINT 0:PROCdisplayfunc(0,0)
930 ENDPROC
940 :
950 DEF PROCscrncolfunc
960 gcol=POINT(mx,my):tint=TINT(mx,my)
970 GCOL gcol TINT tint:RECTANGLE FILL 0,704,250,56
980 ENDPROC
990 :
1000 DEF PROCpictureplot(plotcode)
1010 PROCdriversdisplay(2,1)
1020 pixx=(mx-256) DIV dotx:pixy=?noofrows-(my DIV doty)-1
1030 PLOT plotcode,(editx+pixx)*dotsize,1023-4*(edity+pixy)
1040 PROCdriversdisplay(1,1)
1050 ENDPROC
1060 :
1070 DEF PROCdrawingfunc
1080 MOUSE RECTANGLE 256,0,1023,1023
1090 REPEAT
1100 PROCpictureplot(69):PLOT 69,pixx*dotsize,1023-4*pixy
1110 RECTANGLE FILL 256+pixx*dotx,(my DIV doty)*doty,dotx-2,doty-4
1120 MOUSE mx,my,mb
1130 UNTIL mb<>4
1140 MOUSE RECTANGLE 0,0,1280,1024
1150 ENDPROC
1160 :
1170 DEF PROCcontrolfunc
1180 mx=mx DIV 84:my=my DIV 84:mb=0
1190 IF mx=1 AND my=1 THEN PROCzoomingfunc ELSE PROCdisplayfunc(mx-1,-my+1)
1200 ENDPROC
1210 :
1220 DEF PROCmenucolfunc
1230 gcol=(mx DIV 64)*16+(my-256) DIV 28:tint=(mx DIV 16)*64
1240 GCOL gcol TINT tint:RECTANGLE FILL 0,704,250,56
1250 ENDPROC
1260 :
1270 DEF PROCeditingfunc
1280 PROCdriversdisplay(2,2):MOUSE RECTANGLE 0,0,1024,768
1290 dotstyle=0:delay=INKEY(20):*FX 21,9
1300 GCOL 3,63:PROCsquare
1310 REPEAT
1320 PROCsquare:MOUSE mx,my,mb:dotstyle=(dotstyle+1) MOD 8:PROCsquare
1330 UNTIL mb=2
1340 PROCsquare:GCOL gcol TINT tint
1350 editx=mx DIV dotsize:edity=256-((my+256) DIV 4)
1360 PROCdisplayfunc(0,0):MOUSE RECTANGLE 0,0,1280,1024
1370 ENDPROC
1380 :
1390 DEF PROCwipeoutfunc
1400 PRINT TAB(0,0)"CLEAR SCREEN! ... (Y/N)?"
1410 REPEAT:ans$=GET$:UNTIL INSTR("YyNn",ans$)
1420 IF INSTR("Yy",ans$) THEN
1430 PROCdriversdisplay(2,1):GCOL gcol+128 TINT tint:CLG
1440 PROCdriversdisplay(1,1)
1450 ENDIF
1460 PROCdisplayfunc(0,0)
1470 ENDPROC
1480 :
1490 DEF PROCsquare
1500 VDU 23,6,&FCFC>>dotstyle|
1510 PLOT 4,mx,my:WAIT
1520 PLOT 21,mx+252,my:PLOT 21,mx+252,my+252
1530 PLOT 21,mx,my+252:PLOT 21,mx,my
1540 ENDPROC
1550 :
1560 DEF PROCzoomingfunc
1570 GCOL 56:PROCshowzoom:zoom=(zoom+1) MOD 3
1580 GCOL 63:PROCshowzoom:GCOL gcol TINT tint
1590 dotx=(4*dotsize)<<zoom:cols=(bytesrow*0.2)>>>zoom
1600 doty=16<<zoom:rows=64>>>zoom:?bloksize=1<<zoom
1610 ?noofcols=cols:maxix=bytesrow-cols:IF editx>maxix THEN editx=maxix
1620 ?noofrows=rows:maxiy=256-rows:IF edity>maxiy THEN edity=maxiy
1630 PROCdisplayfunc(0,0):delay=INKEY(20)
1640 ENDPROC
1650 :
1660 DEF PROCshowzoom
1670 RECTANGLE 80+zoom*16,80+zoom*16,84-zoom*32,84-zoom*32
1680 ENDPROC
1690 :
1700 DEF PROCdisplayfunc(alterx,altery)
1710 editx+=alterx:IF editx<0 OR editx>maxix THEN editx-=alterx
1720 edity+=altery:IF edity<0 OR edity>maxiy THEN edity-=altery
1730 PROCdriversdisplay(2,1)
1740 PLOT 4,editx*dotsize,1023-edity*4:PLOT 0,255,-255:*SGET temp
1750 PROCdriversdisplay(1,1):*SCHOOSE temp
1760 PLOT &ED,0,768:CALL enlarger:*SDELETE temp
1770 ENDPROC
1780 :
1790 DEF PROCdriversdisplay(drivers,display)
1800 OSCLI("FX 112,"+STR$(drivers)):OSCLI("FX 113,"+STR$(display))
1810 ENDPROC
1820 :
1830 DEF PROCcontinue
1840 PRINT'"Press <SPACE> to continue ...";:REPEAT UNTIL GET=32:*FX 21,9
1850 ENDPROC
1860 :
1870 DEF PROCeditorscreen
1880 MODE validmode
1890 PROCdriversdisplay(1,2):PROCshowcontrols:PROCshowcolours
1900 PROCdriversdisplay(1,1):PROCzoomingfunc :*POINTER
1910 ENDPROC
1920 :
1930 DEF PROCshowcontrols
1940 GCOL 128 TINT 192:CLG:OFF:GCOL 52
1950 RECTANGLE FILL 0, 0,251,251:GCOL 0
1960 RECTANGLE FILL 16,16,219,219
1970 PLOT 4,-68,124:PLOT 4,124,-68:PLOT 117,319,124:GCOL 56
1980 PLOT 4,0,124:PLOT 4,124,0:PLOT 117,251,124:GCOL 0
1990 PLOT 4, 23,124:PLOT 4,124,23:PLOT 117,228,124
2000 RECTANGLE FILL 44,44,163,163:GCOL 56
2010 FOR zoom=0 TO 1:PROCshowzoom:NEXT
2020 GCOL 128 TINT 0
2030 ENDPROC
2040 :
2050 DEF PROCshowcolours
2060 mx=255:my=703:PROCmenucolfunc
2070 FOR G%=0 TO 63
2080 FOR T%=0 TO 3
2090 GCOL G% TINT T%*64
2100 RECTANGLE FILL (G% DIV 16)*64+T%*16,256+(G% MOD 16)*28,10,20
2110 NEXT:NEXT:ENDPROC
2120 :
2130 DEF PROCoptionscreen
2140 OFF:RESTORE:step%=1:barcol%=0
2150 VDU 19,0,24,0,0,240:COLOUR 0:COLOUR 136
2160 FOR rgb%=0 TO 15:VDU 19,rgb%,16,0,rgb%*16,240:NEXT
2170 FOR bars%=0 TO 55
2180 GCOL barcol%+7:RECTANGLE 0,bars%*4,1280,0
2190 barcol%+=step%:IF barcol%<0 OR barcol%>3 THEN step%=-step%
2200 NEXT
2210 FOR box%=0 TO 3
2220 FOR S%=0 TO 7
2230 GCOL 15-S%
2240 RECTANGLE FILL 16+box%*320+S%*4,32+S%*4,286-S%*8,156-S%*8
2250 NEXT
2260 READ title$:PRINT TAB(box%*20+3,28)title$
2270 NEXT
2280 VDU 28,0,24,79, 0:COLOUR 15:COLOUR 128:CLS
2290 ENDPROC
2300 :
2310 DATA "<STAR> command","<LOAD> picture","<SAVE> picture","<EDIT> picture"
2320 :
2330 DEF PROCassemble(param1,param2,param3)
2340 bytesrow=param1:dotsize=param2:banksize=param3
2350 DIM space 256:space!0=148:space!4=-1:OFF
2360 SYS &31,space,space+&10
2370 bank1adr=space!&10
2380 bank2adr=bank1adr+banksize
2390 FOR assemble=0 TO 2 STEP 2
2400 P%=space
2410 [ OPT assemble
2420 ALIGN
2430 .enlarger
2440 LDR R0,smallpic
2450 LDR R1,largepic
2460 LDRB R2,noofrows;number of rows
2470 .rowsloop
2480 LDRB R3,noofcols;number of columns
2490 MOV R7,R0
2500 .colsloop
2510 LDRB R4,[R7],#&01;load and expand
2520 ORR R4,R4,R4,ASL #8
2530 ORR R4,R4,R4,ASL #16
2540 LDRB R5,bloksize
2550 .width
2560 MOV R8,R1
2570 LDRB R6,bloksize
2580 .depth
2590 STR R4,[R8],#bytesrow
2600 STR R4,[R8],#bytesrow
2610 STR R4,[R8],#bytesrow
2620 STR R4,[R8],#bytesrow
2630 SUBS R6,R6,#&01
2640 BNE depth
2650 ADD R1,R1,#4
2660 SUBS R5,R5,#&01
2670 BNE width
2680 SUBS R3,R3,#&01
2690 BNE colsloop
2700 ADD R0,R0,#bytesrow
2710 SUB R1,R8,#bytesrow*0.8-4
2720 SUBS R2,R2,#&01
2730 BNE rowsloop
2740 MOV R15,R14
2750 .transfer; this routine transfers
2760 LDR R0,smallpic; copy of the pic
2770 LDR R1,datadata; from
2780 MOV R2,R1 ;bank 1 to bank 2
2790 .transloop
2800 LDR R3,[R0],#4
2810 STR R3,[R1],#4
2820 CMP R0,R2
2830 BNE transloop
2840 MOV R15,R14
2850 .smallpic EQUD bank1adr
2860 .largepic EQUD bank1adr+0.2*bytesrow
2870 .datadata EQUD bank2adr
2880 .noofrows EQUB -1
2890 .noofcols EQUB -1
2900 .bloksize EQUB -1
2910 ]
2920 NEXT assemble
2930 CALL transfer
2940 ENDPROC
2950 :
2960 DEF PROCsetup
2970 REPEAT
2980 PRINT "Please select mode"''"Press <1> for 13 or <2> for 15 ";
2990 REPEAT:key=GET-48:UNTIL key=1 OR key=2
3000 IF NOT FNramtest(key) THEN PRINT''"You must configure more RAM for this mode":PROCcontinue:CLS
3010 UNTIL FNramtest(key)
3020 validmode=2*key+11:CLS:OFF:PROCvalidatemode
3030 mx=640:editx=0:my=512:edity=0:noerror=TRUE
3040 IF key=1 THEN MODE 13 ELSE MODE 15
3050 PROCdriversdisplay(2,2):CLS
3060 ENDPROC
3070 :
3080 DEF PROCerror
3090 PROCdriversdisplay(1,1):CLS
3100 IF ERR=17 AND INKEY(-2) THEN
3110 noerror=FALSE
3120 ELSE
3130 REPORT
3140 IF (ERR AND &FF)<127 THEN PRINT" at line ";ERL ELSE PRINT
3150 IF ERR=17 PRINT"Use Ctrl-Esc to quit"
3160 VDU7:PROCcontinue
3170 ENDIF
3180 ENDPROC
3190 :
3200 DEFFNscrnsize
3210 !B%=150:!(B%+4)=-1
3220 SYS&31,B%,B%+&10:=!(B%+&10)/1024
3230 :
3240 DEFFNramtest(size)
3250 =(160*size<=FNscrnsize)
3260 :
3270 DEFPROCmessage
3280 PRINT"Your machine must have at least 160K of screen RAM for this program"
3290 PRINT"You will need 320K to use mode 15"'
3300 PRINT"Please reconfigure with:"
3310 PRINT" *CONFIGURE SCREENSIZE 20"'"or *CONFIGURE SCREENSIZE 40"
3320 VDU7:ENDPROC