Difference between revisions of "ACU March 1985 - Type-ins"
Line 3: | Line 3: | ||
__TOC__ | __TOC__ | ||
=Downloads= | =Downloads= | ||
− | [[media: | + | [[media:Acu_march_1985.zip|Disk Image]] |
=Cover Image= | =Cover Image= | ||
− | [[image: | + | [[image:Acu_march_1985_cover.png]] |
=Boolean operations demonstration= | =Boolean operations demonstration= |
Revision as of 11:14, 1 June 2009
Return to ACU Type-Ins
Contents
- 1 Downloads
- 2 Cover Image
- 3 Boolean operations demonstration
- 4 Electric Eddy
- 5 Electric Fencing
- 6 Flashman
- 7 Jeremy Vine's music routine
- 8 Machine code fill routine and demonstration
- 9 Manipulating the Amstrad CPC464 Screen Display
- 10 Number Sort routine
- 11 Prime Numbers (1)
- 12 Prime Numbers (2)
- 13 Screen Dump (DMP1)
- 14 Screen Dump (Epson)
- 15 Sum Numbers
- 16 Trench
- 17 Unerase
Downloads
Cover Image
Boolean operations demonstration
To run Boolean operations demonstration, type:
RUN"BOOLEAN"
Electric Eddy
To run Electric Eddy, type:
RUN"EDDY"
Electric Fencing
To run Electric Fencing, type:
RUN"FENCING"
Flashman
To run Flashman, type:
RUN"FLASHMAN"
Jeremy Vine's music routine
To run Jeremy Vine's music routine, type:
RUN"MUSIC"
Machine code fill routine and demonstration
To run Machine code fill routine and demonstration, type:
RUN"MCFILL"
Manipulating the Amstrad CPC464 Screen Display
The Z80 assembler code for the "Manipulating the Amstrad CPC464 Screen Display" article.
See Amstrad Computer User, March 1985 for more details.
Routine 1
ORG &8000 .start LD HL,XXXX ; address of top left corner of area LD DE,XXXX ; address of store area LD B,8 .loop1 PUSH BC PUSH HL LD B,8 ; number of horizontal lines .loop2 LD A,(HL) LD (DE),A INC DE INC HL DJNZ loop2 POP HL LD BC,&0000 ; add &0800 to screen address ADD HL,BC JR NC,loopend ; jump if total not more than &FFFF LD BC,&3FB0 AND A ; else subtract &3FB0 SBC HL,BC .loopend POP BC DJNZ loop1 RET
Routine 2
ORG &4000 .pixstr DEFB 0 .start LD HL,&C000 ; Address of top-left corner of screen LD E,&88 ; mask for left-most pixel in byte LD B,200 ; number of pixel lies in screen .loop1 PUSH BC PUSH HL ; save address of first byte on stack LD A,(HL) ; get first screen byte AND E ; mask off all pixels except left-most LD (pixstr),A ; store pixel for later CPL AND (HL) ; blank out pixel LD (HL),A ; update screen RLC (HL) ; rotate screen byte left LD B,79 ; number of bytes in line minus one .loop2 INC HL ; next byte LD A,(HL) AND E ; mask off all pixels except left-most LD D,A ; save pixel for later CPL AND (HL) ; blank out pixel LD (HL),A ; update screen RLC (HL) ; rotate screen byte left LD A,D ; recover pixel .loop3 RRC E ; rotate mask right one bit JR C,out1 ; jump out when mask bit rotates out SRL A ; else shift pixel right JR loop3 ; and repeat .out1 DEC HL ; back to previous byte OR (HL) LD (HL),A ; insert pixel into screen byte INC HL ; restore screen address DJNZ loop2 ; jump back unless finished with line LD A,(pixstr) ; recall stored pixel .loop4 RRC E ; rotate mask right one bit JR C,out2 ; jump out when mask bit rotates out SRL A ; else shift pixel right JR loop4 ; and repeat .out2 OR (HL) LD (HL),A ; insert pixel into screen byte POP HL LD BC,&0800 ADD HL,BC ; next line down JR NC,end ; jump if total not greater than &FFFF AND A LD BC,&3FB0 SBC HL,BC ; else subtract &3FB0 .end POP BC DJNZ loop1 ; jump back unless finished RET
Routine 3
ORG &4000 .pixstr DEFB 0 .start LD HL,&C04F ; Address of top-left corner of screen LD E,&11 ; mask for left-most pixel in byte LD B,200 ; number of pixel lies in screen .loop1 PUSH BC PUSH HL ; save address of first byte on stack LD A,(HL) ; get first screen byte AND E ; mask off all pixels except left-most LD (pixstr),A ; store pixel for later CPL AND (HL) ; blank out pixel LD (HL),A ; update screen RRC (HL) ; rotate screen byte left LD B,79 ; number of bytes in line minus one .loop2 DEC HL ; next byte LD A,(HL) AND E ; mask off all pixels except left-most LD D,A ; save pixel for later CPL AND (HL) ; blank out pixel LD (HL),A ; update screen RRC (HL) ; rotate screen byte left LD A,D ; recover pixel .loop3 RLC E ; rotate mask right one bit JR C,out1 ; jump out when mask bit rotates out SLA A ; else shift pixel right JR loop3 ; and repeat .out1 INC HL ; back to previous byte OR (HL) LD (HL),A ; insert pixel into screen byte DEC HL ; restore screen address DJNZ loop2 ; jump back unless finished with line LD A,(pixstr) ; recall stored pixel .loop4 RLC E ; rotate mask right one bit JR C,out2 ; jump out when mask bit rotates out SLA A ; else shift pixel right JR loop4 ; and repeat .out2 OR (HL) LD (HL),A ; insert pixel into screen byte POP HL LD BC,&0800 ADD HL,BC ; next line down JR NC,end ; jump if total not greater than &FFFF AND A LD BC,&3FB0 SBC HL,BC ; else subtract &3FB0 .end POP BC DJNZ loop1 ; jump back unless finished RET
Routine 4
ORG &4000 .start LD HL,&C000 ; top left corner of screen address LD B,200 ; number of pixel lines .loop1 PUSH BC PUSH HL ; save line start address on stack XOR A ; zero accumulator and clear carry flag LD B,80 ; number of bytes in line .loop2 RR (HL) ; rotate right, carry to d7, d0 to array INC HL ; next byte DJNZ loop2 ; loop until finished with line POP HL ; recover address of first byte in line RRA ; rotate last bit from carry into A OR (HL) LD (HL),A ; insert pixel into first byte LD BC,&0800 ADD HL,BC ; next pixel line JR NC,end ; jump if total not greater than &FFFF AND A LD BC,&3FB0 SBC HL,BC ; else subtract &3FB0 .end POP BC DJNZ loop1 ; loop unless finished RET
Routine 5
ORG &4000 .start LD HL,&C04F ; top left corner of screen address LD B,200 ; number of pixel lines .loop1 PUSH BC PUSH HL ; save line start address on stack XOR A ; zero accumulator and clear carry flag LD B,80 ; number of bytes in line .loop2 RL (HL) ; rotate right, carry to d7, d0 to array DEC HL ; next byte DJNZ loop2 ; loop until finished with line POP HL ; recover address of first byte in line RLA ; rotate last bit from carry into A OR (HL) LD (HL),A ; insert pixel into first byte LD BC,&0800 ADD HL,BC ; next pixel line JR NC,end ; jump if total not greater than &FFFF AND A LD BC,&3FB0 SBC HL,BC ; else subtract &3FB0 .end POP BC DJNZ loop1 ; loop unless finished RET
Number Sort routine
To run Number Sort routine, type:
RUN"SORT"
Prime Numbers (1)
To run Prime Numbers (1), type:
RUN"PASCAL3"
Prime Numbers (2)
To run Prime Numbers (2), type:
RUN"PASCAL4"
Screen Dump (DMP1)
The Z80 assembler code for the DMP1 Screen Dump program.
The machine code can be loaded in BASIC using DMPLIST2.BAS and DMPLIST4.BAS.
See Amstrad Computer User, March 1985 for more details.
ORG &8000 .entry EQU $ LD HL,&E9E1 ; Start RELOCATOR LD (&30),HL RST &30 .this EX DE,HL LD HL,rel_table-this ADD HL,DE ; HL has absolute address of rel_table .loop LD C,(HL) INC HL LD B,(HL) ; BC has first entry in table LD A,C OR B JR Z,done ; entry was 0000 so exit loop PUSH HL ; stack current table pointer LD H,B LD L,C ADD HL,DE ; make table entry absolute PUSH HL ; and stack this value LD C,(HL) INC HL LD B,(HL) ; get contents pointed to by entry LD H,B LD L,C ADD HL,DE ; make this absolute LD B,H LD C,L POP HL ; retrieve absolute entry value LD (HL),C INC HL LD (HL),B ; store absolute value at this address POP HL ; get address of previous table entry INC HL ; make HL point at next JR loop .done EQU $ ; end of RELOCATOR KL_NEW_FRAME_FLY EQU &BCD7 KM_TEST_KEY EQU &BB1E COPY_key EQU 9 CTRL_key EQU 23 SHIFT_key EQU 21 .r01 LD HL,tick_block-this ; set-up EVENT LD B,%10000001 LD C,0 .r02 LD DE,int_routine-this CALL KL_NEW_FRAME_FLY RET .int_routine EQU $ ; this is the interrupt routine PUSH BC PUSH DE PUSH HL PUSH AF LD A,COPY_key CALL KM_TEST_KEY JR Z,return LD A,CTRL_key CALL KM_TEST_KEY JR Z,return .r03 CALL scrndump-this .return POP AF POP HL POP DE POP BC RET .tick_block DEFS 9 .FRED DEFS 7 .scrndump EQU $ GRA_TEST_ABSOLUTE EQU &BBF0 MC_PRINT_CHAR EQU &BD2B MC_BUSY_PRINTER EQU &BD2E ; DMP1DUMP .r04 LD IX,FRED-this LD (IX+1),0 ; x coord = 0 LD (IX+2),0 LD (IX+3),&90 ; y coord = 400 LD (IX+4),&01 LD (IX+5),0 ; line count = 0 LD (IX+0),0 ; byte out = 0 .MAIN CALL MC_BUSY_PRINTER JR C,MAIN LD A,&1B CALL MC_PRINT_CHAR ; ESC LD A,&4B CALL MC_PRINT_CHAR ; "K" LD A,&02 CALL MC_PRINT_CHAR LD A,&40 CALL MC_PRINT_CHAR ; &240 .LINE EQU $ LD (IX+0),0 ; byte out = 0 LD (IX+6),0 ; 7-bit count = 0 .BYTE SRA (IX+0) LD E,(IX+1) ; FRED + 1 - 2 = x coord LD D,(IX+2) LD L,(IX+3) ; FRED + 3 - 4 = y coord LD H,(IX+4) CALL GRA_TEST_ABSOLUTE OR A JR Z,NOSET SET 6,(IX+0) ; +0 is byte being built .NOSET INC (IX+6) ; increase bit count LD A,(IX+6) ; and get it CP 7 JR Z,PRINT ; if got 7 bits the print LD L,(IX+3) ; get y coord LD H,(IX+4) DEC HL ; use HL for simple 16 bit maths DEC HL ; move down by 2 (1 pixel) LD (IX+3),L ; then put it back LD (IX+4),H JR BYTE .MID_JMP JR MAIN ; to relative jump more than 128 .PRINT CALL MC_BUSY_PRINTER JR C,PRINT ; wait until it's free LD A,(IX+0) ; get byte output CALL MC_PRINT_CHAR ; and print it INC (IX+1) INC (IX+1) ; move x coord on by 2 JR NZ,NOHIGH INC (IX+2) ; handle high byte if necessary .NOHIGH LD A,(IX+1) SUB &82 JR NZ,RESETY LD A,(IX+2) CP 2 JR Z,ENDLIN ; x coord = &282 .RESETY LD L,(IX+3) LD H,(IX+4) LD DE,&000C ADD HL,DE LD (IX+3),L ; increase y coord by 12 LD (IX+4),H JR LINE .ENDLIN INC (IX+5) ; increment line count LD A,&0A ; Line Feed CALL MC_PRINT_CHAR LD A,&0D ; Carriage Return CALL MC_PRINT_CHAR LD A,SHIFT_key CALL KM_TEST_KEY ; check id SHIFT is pressed JR NZ,BYE LD (IX+1),0 ; set x coord to zero LD (IX+2),0 LD A,(IX+5) ; get line count CP &22 JR NZ,MID_JMP ; have we got 34 lines (7 high) .BYE EQU $ LD A,15 CALL MC_PRINT_CHAR LD A,13 CALL MC_PRINT_CHAR RET .rel_table EQU $ DEFW r01-this+1 DEFW r02-this+1 DEFW r03-this+1 DEFW r04-this+2 ; address in IX operator is 3 and 4 DEFW 0
Screen Dump (Epson)
The Z80 assembler code for the Epson Screen Dump program.
The machine code can be loaded in BASIC using DMPLIST2.BAS and DMPLIST4.BAS.
See Amstrad Computer User, March 1985 for more details.
ORG &8000 .entry EQU $ LD HL,&E9E1 ; Start RELOCATOR LD (&30),HL RST &30 .this EX DE,HL LD HL,rel_table-this ADD HL,DE ; HL has absolute address of rel_table .loop LD C,(HL) INC HL LD B,(HL) ; BC has first entry in table LD A,C OR B JR Z,done ; entry was 0000 so exit loop PUSH HL ; stack current table pointer LD H,B LD L,C ADD HL,DE ; make table entry absolute PUSH HL ; and stack this value LD C,(HL) INC HL LD B,(HL) ; get contents pointed to by entry LD H,B LD L,C ADD HL,DE ; make this absolute LD B,H LD C,L POP HL ; retrieve absolute entry value LD (HL),C INC HL LD (HL),B ; store absolute value at this address POP HL ; get address of previous table entry INC HL ; make HL point at next JR loop .done EQU $ ; end of RELOCATOR KL_NEW_FRAME_FLY EQU &BCD7 KM_TEST_KEY EQU &BB1E COPY_key EQU 9 CTRL_key EQU 23 SHIFT_key EQU 21 .r01 LD HL,tick_block-this ; set-up EVENT LD B,%10000001 LD C,0 .r02 LD DE,int_routine-this CALL KL_NEW_FRAME_FLY RET .int_routine EQU $ ; this is the interrupt routine PUSH BC PUSH DE PUSH HL PUSH AF LD A,COPY_key CALL KM_TEST_KEY JR Z,return LD A,CTRL_key CALL KM_TEST_KEY JR Z,return .r03 CALL scrndump-this .return POP AF POP HL POP DE POP BC RET .tick_block DEFS 9 .FRED DEFS 7 .scrndump EQU $ GRA_TEST_ABSOLUTE EQU &BBF0 MC_PRINT_CHAR EQU &BD2B MC_BUSY_PRINTER EQU &BD2E ; EPSONDUMP .r04 LD IX,FRED-this LD (IX+1),0 ; x coord = 0 LD (IX+2),0 LD (IX+3),&90 ; y coord = 400 LD (IX+4),&01 LD (IX+5),0 ; line count = 0 LD (IX+0),0 ; byte out = 0 LD A,&1B CALL MC_PRINT_CHAR LD A,&41 CALL MC_PRINT_CHAR LD A,&06 CALL MC_PRINT_CHAR .MAIN CALL MC_BUSY_PRINTER JR C,MAIN LD A,&1B CALL MC_PRINT_CHAR ; ESC LD A,&4B CALL MC_PRINT_CHAR ; "K" LD A,&40 CALL MC_PRINT_CHAR LD A,&02 CALL MC_PRINT_CHAR ; &240 .LINE EQU $ LD (IX+0),0 ; byte out = 0 LD (IX+6),0 ; 7-bit count = 0 .BYTE SLA (IX+0) LD E,(IX+1) ; FRED + 1 - 2 = x coord LD D,(IX+2) LD L,(IX+3) ; FRED + 3 - 4 = y coord LD H,(IX+4) CALL GRA_TEST_ABSOLUTE OR A JR Z,NOSET SET 0,(IX+0) ; +0 is byte being built .NOSET INC (IX+6) ; increase bit count LD A,(IX+6) ; and get it CP 7 JR Z,PRINT ; if got 7 bits the print LD L,(IX+3) ; get y coord LD H,(IX+4) DEC HL ; use HL for simple 16 bit maths DEC HL ; move down by 2 (1 pixel) LD (IX+3),L ; then put it back LD (IX+4),H JR BYTE .MID_JMP JR MAIN ; to relative jump more than 128 .PRINT CALL MC_BUSY_PRINTER JR C,PRINT ; wait until it's free LD A,(IX+0) ; get byte output CALL MC_PRINT_CHAR ; and print it INC (IX+1) INC (IX+1) ; move x coord on by 2 JR NZ,NOHIGH INC (IX+2) ; handle high byte if necessary .NOHIGH LD A,(IX+1) SUB &82 JR NZ,RESETY LD A,(IX+2) CP 2 JR Z,ENDLIN ; x coord = &282 .RESETY LD L,(IX+3) LD H,(IX+4) LD DE,&000C ADD HL,DE LD (IX+3),L ; increase y coord by 12 LD (IX+4),H JR LINE .ENDLIN INC (IX+5) ; increment line count LD A,&0A ; Line Feed CALL MC_PRINT_CHAR LD A,&0D ; Carriage Return CALL MC_PRINT_CHAR LD A,SHIFT_key CALL KM_TEST_KEY ; check id SHIFT is pressed JR NZ,BYE LD (IX+1),0 ; set x coord to zero LD (IX+2),0 LD A,(IX+5) ; get line count CP &22 JR NZ,MID_JMP ; have we got 34 lines (7 high) .BYE EQU $ LD A,15 CALL MC_PRINT_CHAR LD A,13 CALL MC_PRINT_CHAR RET .rel_table EQU $ DEFW r01-this+1 DEFW r02-this+1 DEFW r03-this+1 DEFW r04-this+2 ; address in IX operator is 3 and 4 DEFW 0
Sum Numbers
To run Sum Numbers, type:
RUN"PASCAL5"
Trench
To run Trench, type:
RUN"TRENCH"
Unerase
The Z80 assembler code for David Link's Unerase program.
See Amstrad Computer User, March 1985 for more details.
; Unerase a file in CP/M - 04/11/84 ; Copyright David Link 1984 ; A program to unerase a file that has been accidentally ; erased. Should be used immediately after erasing the ; file since if user later, some blocks may have been re-used. ; Format is - UNERA filename DEFCB EQU &5C fnamelen EQU 8 extlen EQU 3 extent EQU 12 dirlen EQU 32 ; CP/M BDOS call numbers OPEN EQU 15 CLOSE EQU 16 SEARCH EQU 17 SRCH_AGAIN EQU 18 MAKE EQU 22 SETDMA EQU 26 ; Default workspace for file reads tbuff EQU 128 ; Macro to call CP/M setting DE and C DOS MAC LD DE,=0 LD C,=1 CALL Dos ENDM ; Macro to call CP/M setting C. SDOS MAC LD C,=0 CALL Dos ENDM ; COM files begin at &100 ORG &100 LD SP,(6) ; set stack to top of TPA DOS DEFCB,SEARCH ; Does file exist? INC A JP NZ,0 ; File exists, return to CCP LD HL,FCBSPACE ; Initialise pointer to current FCB LD (FCBPTR),HL DOS tbuff,SETDMA ; set disc I/O to tbuff DOS DUMFCB,SEARCH ; and search for the first entry in directory More_Search INC A JR Z,End_of_Directory ; No more entries ; Compare found filename with the required filename Continue DEC A ; adjust because we INCed it ADD A,A ; multiply by dirlen to get postion ADD A,A ; of entry in catalogue ADD A,A ADD A,A ADD A,A LD D,0 LD E,A LD HL,tbuff ; point to found file ADD HL,DE Again PUSH HL ; and compare it with required filename INC HL LD B,fnamelen+extlen ; both name and type (8, name : 3, type) LD DE,DEFCB+1 ; filename starts at FCB + 1 Match LD A,(DE) LD C,(HL) RES 7,C ; some CP/Ms set bits on filename CP C ; so make sure top bit is reset for comparison INC HL INC DE JR NZ,NoMatch ; not this one DJNZ Match ; good so far... keep going ; Match found POP HL ; filename match, but... PUSH HL LD A,(HL) ; ... is it erased? CP &E5 ; e% in first byte of directory = erased JR NZ,NoMatch ; not erased... so search some more LD (HL),0 ; it was erased, so unerase it LD DE,(FCBPTR) ; and store the FCB information in LD BC,dirlen ; our temporary table LDIR LD (FCBPTR),DE ; updating our table pointer afterwards ; Search for another entry NoMatch POP HL DOS DUMFCB,SRCH_AGAIN ; search for next entry in directory JR More_Search ; we have now exhausted the directory search and built ; up our table of directory entries for the required file End_of_Dir LD DE,FCBSPACE ; start processing table of matched ; directory entries MAIN_LOOP LD HL,(FCBPTR) ; have we reached end of table? OR A SBC HL,DE JP Z,0 ; finished, so return PUSH DE ; save table pointer LD HL,extent ; address extent byte ADD HL,DE LD A,(HL) ; make an extent of new, LD (DEFCB+extent),a ; unerased file... DOS DEFCB,MAKE POP DE ; recover pointer to FCB... SDOS CLOSE ; and close it LD HL,dirlen ADD HL,DE ; have we reached end of table? EX DE,HL JR MAIN_LOOP Dos PUSH HL PUSH DE PUSH BC CALL 5 POP BC POP DE POP HL RET FCBPTR DEFS 2 DUMFCB DEFM "????????????" DEFW 0,0 DEFS 16 DEFW 0,0 FCBSPACE EQU $