10 REM Z80 Disassembler
20 REM By R.A.Waddilove
30 REM(c)Computing With The Amstrad
40 DEFINT b-z
50 MODE 1:INK 0,0:BORDER 0:PEN 1:PAPER 3
60 LOCATE 1,25:PRINT "        Press SPACE BAR for menu        ";
70 LOCATE 1,1:PRINT "      Z80   Disassembler/Hex dump      ":PRINT:PAPER 0:WINDOW #0,1,39,2,24:PRINT
80 DIM r$(7),s$(3),q$(3),c$(7),x$(7)
90 FOR i=0 TO 7:READ r$(i),c$(i),x$(i):NEXT
100 DATA B,NZ,"ADD A,",C,Z,"ADC A,",D,NC,SUB,E,C,"SBC A,",H,PO,AND,L,PE,XOR,x,P,OR,A,M,CP
110 FOR i=0 TO 3:READ s$(i),q$(i):NEXT
120 DATA BC,BC,DE,DE,y,y,SP,AF
130 FOR i=0 TO 69:READ char$:POKE &B448+i,VAL("&"+char$):NEXT
140 DATA DD,4E,00,CD,15,B9,DD,6E,02,DD,66,03,77,23,36,00,C9,DD,4E,00,CD,0F,B9,C5,DD,6E,04,DD,66,05,7E,DD,6E,02,DD,66,03,77,23,36,00,C1,C3,18,B9,CD,06,B9,F5,DD,6E,00,DD,66,01,7E,DD,6E,02,DD,66,03,77,23,36,00,F1,C3,0C,B9
150 PEN 2:PRINT TAB(6)"ROM's.....":PRINT:j=0:byte=0
160 FOR i=0 TO 251
170 CALL &B448,àbyte,i
180 IF byte<>&80 THEN PEN 2:PRINT TAB(6)i;CHR$(15);CHR$(3);": ";:PEN 1 ELSE IF NOT j THEN PEN 2:PRINT TAB(6)i;CHR$(15);CHR$(3);": ";:PEN 1:PRINT"On Board ROM (BASIC).":j=-1
190 IF byte=0 THEN PRINT "Foreground ROM." ELSE IF byte=1 THEN PRINT "Background ROM." ELSE IF byte=3 THEN PRINT "Extension Foreground ROM."
200 NEXT
210 PEN 2:PRINT:INPUT "Start address";a
220 IF a<0 THEN a=65536+a
230 IF a>49151 THEN PRINT CHR$(11);SPC(35);CHR$(13);:INPUT "Which ROM";rom ELSE rom=255
240 IF a<&4000 THEN PRINT CHR$(11);SPC(35);CHR$(13);:INPUT "ROM or RAM";char$:IF UPPER$(char$)="ROM" THEN rom=254
250 PRINT CHR$(11);SPC(35);CHR$(13);:INPUT "Printer (Y/N)";char$:IF UPPER$(char$)="Y" THEN stream=8 ELSE stream=0
260 PRINT CHR$(11);SPC(35);CHR$(13);:INPUT "Hex or Disassemble (H/D)";opt$:CLS:IF UPPER$(opt$)="H" THEN 1110
270 PEN #1,1:PAPER #1,3:PRINT #1,CHR$(30);"Addr:Hex           Mnemonic       ASCII "
280 dis$="":char$=""
290 PEN 2:PRINT #stream,TAB(20)dis$;:PEN 1:PRINT #stream,TAB(35)char$
300 class=0:index=0:char$=""
310 PRINT #stream,HEX$(a,4);":";:PEN 3
320 GOSUB 530
330 IF byte=&76 THEN IF class=0 AND index=0 THEN dis$="HALT":GOTO 290
340 IF byte=&CB THEN class=1:GOTO 320
350 IF byte=&ED THEN IF CLASS<>1 THEN class=2:GOTO 320 ELSE 380
360 IF byte=&DD THEN IF CLASS<>1 THEN index=1:GOTO 320 ELSE 380
370 IF byte=&FD THEN IF CLASS<>1 THEN index=2:GOTO 320 ELSE 380
380 IF class=0 THEN ON f+1 GOSUB 690,820,840,860
390 IF class=1 AND index>0 THEN GOSUB 530:a=a-2
400 IF class=1 THEN ON f+1 GOSUB 960,970,980,990
410 IF class=2 THEN ON f GOSUB 1010,1100
420 x1=INSTR(dis$,"x"):y1=INSTR(dis$,"y")
430 IF index=1 AND x1>0 THEN GOSUB 630:dis$=LEFT$(dis$,x1-1)+"(IX+&"+HEX$(byte)+")"+MID$(dis$,x1+1):IF class<>1 THEN GOSUB 590 ELSE a=a+2
440 IF index=1 AND y1>0 THEN dis$=LEFT$(dis$,y1-1)+"IX"+MID$(dis$,y1+1):GOTO 420
450 IF index=0 AND y1>0 THEN dis$=LEFT$(dis$,y1-1)+"HL"+MID$(dis$,y1+1):GOTO 420
460 IF index=0 AND x1>1 THEN dis$=LEFT$(dis$,x1-1)+"(HL)"+MID$(dis$,x1+1)
470 IF index=2 AND y1>0 THEN dis$=LEFT$(dis$,y1-1)+"IY"+MID$(dis$,y1+1):GOTO 420
480 IF index=2 AND x1>0 THEN GOSUB 630:dis$=LEFT$(dis$,x1-1)+"(IY+&"+HEX$(byte)+")"+MID$(dis$,x1+1):IF class<>1 THEN GOSUB 590 ELSE a=a+2
490 IF INSTR(dis$,"VV") THEN GOSUB 630:i=byte:a=a+1:GOSUB 630:a=a-1:dis$=LEFT$(dis$,INSTR(dis$,"VV")-1)+"&"+HEX$(i+256*byte)+MID$(dis$,INSTR(dis$,"VV")+2):GOSUB 590:GOSUB 590
500 IF INSTR(dis$,"V") THEN GOSUB 630:dis$=LEFT$(dis$,INSTR(dis$,"V")-1)+"&"+HEX$(byte)+MID$(dis$,INSTR(dis$,"V")+1):GOSUB 590
510 IF INKEY$=" " THEN 210 ELSE 290
520 REM ------- get data -----------
530 GOSUB 630:bit$=BIN$(byte,8)
540 f=VAL("&X"+LEFT$(bit$,2))
550 g=VAL("&X"+MID$(bit$,3,3))
560 h=VAL("&X"+RIGHT$(bit$,3))
570 j=VAL("&X"+MID$(bit$,3,2))
580 k=VAL("&X"+MID$(bit$,5,1))
590 GOSUB 630:IF byte>31 AND byte<127 THEN char$=char$+CHR$(byte) ELSE char$=char$+"."
600 PRINT #stream,HEX$(byte,2);" ";:a=a+1
610 RETURN
620 REM ------- read byte ----------
630 IF rom=255 THEN byte=PEEK(a):RETURN
640 IF rom=254 THEN CALL &B475,àbyte,a:RETURN
650 CALL &B459,a,àbyte,rom
660 RETURN
670 REM ---------- class=0 ---------
680 REM ----------- f=0 ------------
690 ON h+1 GOTO 700,740,750,760,770,780,790,800
700 IF g>3 THEN dis$="JR "+c$(g-4)+",W" ELSE dis$=MID$("NOP      EX AF,AF'DJNZ W   JR W     ",1+g*9,9)
710 GOSUB 630:IF INSTR(dis$,"W")>0 AND byte>127 THEN dis$=LEFT$(dis$,INSTR(dis$,"W")-1)+"&"+HEX$(a+byte-255):GOTO 590
720 IF INSTR(dis$,"W")>0 AND byte<128 THEN dis$=LEFT$(dis$,INSTR(dis$,"W")-1)+"&"+HEX$(1+a+byte):GOTO 590
730 RETURN
740 IF k THEN dis$="ADD y,"+s$(j):RETURN ELSE dis$="LD "+s$(j)+",VV":RETURN
750 dis$="LD "+MID$("(BC),AA,(BC)(DE),AA,(DE)(VV),yy,(VV)(VV),AA,(VV)",1+g*6,6):RETURN
760 IF k THEN dis$="DEC "+s$(j):RETURN ELSE dis$="INC "+s$(j):RETURN
770 dis$="INC "+r$(g):RETURN
780 dis$="DEC "+r$(g):RETURN
790 dis$="LD "+r$(g)+",V":RETURN
800 dis$=MID$("RLCARRCARLA RRA DAA CPL SCF CCF ",1+g*4,4):RETURN
810 REM ----------- f=1 ------------
820 dis$="LD "+r$(g)+","+r$(h):RETURN
830 REM ----------- f=2 ------------
840 dis$=x$(g)+" "+r$(h):RETURN
850 REM ----------- f=3 ------------
860 ON h+1 GOTO 870,880,890,900,910,920,930,940
870 dis$="RET "+c$(g):RETURN
880 IF k THEN  dis$=MID$("RET    EXX    JP (y) LD SP,y",1+j*7,7):RETURN ELSE dis$="POP "+q$(j):RETURN
890 dis$="JP "+c$(g)+",VV":RETURN
900 dis$=MID$("JP VV    *********OUT (V),AIN A,(V) EX (SP),yEX DE,HL DI       EI       ",1+g*9,9):RETURN
910 dis$="CALL "+c$(g)+",VV":RETURN
920 IF k THEN dis$="CALL VV":RETURN ELSE dis$="PUSH "+q$(j):RETURN
930 dis$=x$(g)+" V":RETURN
940 dis$="RST "+MID$("0008101820283038",1+g*2,2):RETURN
950 REM --------- class 1 ---------
960 dis$=MID$("RLCRRCRL RR SLASRA***SRL",1+g*3,3)+" "+r$(h):RETURN
970 dis$="BIT"+STR$(g)+","+r$(h):RETURN
980 dis$="RES"+STR$(g)+","+r$(h):RETURN
990 dis$="SET"+STR$(g)+","+r$(h):RETURN
1000 REM -------- class 2 ---------
1010 ON h+1 GOTO 1020,1030,1040,1050,1060,1070,1080,1090
1020 dis$="IN "+r$(g)+",(C)":RETURN
1030 dis$="OUT (C),"+r$(g):RETURN
1040 IF k THEN dis$="ADC HL,"+s$(j):RETURN ELSE dis$="SBC HL,"+s$(j):RETURN
1050 IF k THEN dis$="LD "+s$(j)+",(VV)":RETURN ELSE dis$="LD (VV),"+s$(j):RETURN
1060 dis$="NEG":RETURN
1070 IF k THEN dis$="RETI":RETURN ELSE dis$="RETN":RETURN
1080 dis$=MID$("IM 0****IM 1IM 2****************",1+g*4,4):RETURN
1090 dis$=MID$("LD I,ALD R,ALD A,ILD A,RRRD   RLD   ************",1+g*6,6):RETURN
1100 dis$=MID$("LDCPINOT********",1+h*2,2)+MID$("********I D IRDR",1+g*2,2):RETURN
1110 REM --------- Hex dump --------
1120 PEN #1,1:PAPER #1,3:PRINT #1,CHR$(30);"Addr        Hex  Dump          ASCII   "
1130 WHILE INKEY$<>" "
1140 PEN 2:PRINT #stream,HEX$(a,4);":";:PEN 1
1150 char$=""
1160 FOR i=0 TO 7
1170 GOSUB 590
1180 NEXT
1190 PEN 3:PRINT #stream," "char$
1200 WEND
1210 GOTO 210