Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - LokalHorst

#1
Inspired by the VDC questions lately, I've hacked in a small routine which multiplies the value of A by 80 decimal. The version following below uses exactly 32 bytes.
I know that a table lookup would be faster, but it consumes n times 2 bytes memory (50 bytes for a 25line lookup), aswell as n times add 80d to the result in a loop would be shorter, but definitely slower.
Anyone who can explain "how does this multiply with right-shifts = division by 2 ?" receives a rep.-point  ;D

;ZP-adresses used
ResLo = $FC
ResHi = $FD

;on entry A is the multiplicator, the result is returned in ResLo = lo byte and ResHi = hi byte (ResHi also in A on return)
;X and Y are used to hold intermediate results

Mul80:
ldx #$00
stx ResLo
lsr
ror ResLo
lsr
ror ResLo
ldy ResLo
sta ResHi
lsr
ror ResLo
lsr
ror ResLo
tax
tya
adc ResLo
sta ResLo
txa
adc ResHi
sta ResHi
RTS

#2
CP/M / Little Helper Tool
June 08, 2010, 09:36 AM
This is only possible within C128 CP/M -> switch to a different CPU (in this specific case starting the build-in ML-Monitor)

As Commodore left out a lot of documentation, software regarding CP/M, I once started to explore this mode myself with the help of the following little program.
It can be used to transfer files from normal CBM disks to CP/M in combination with save.com (reduces TPA by 800h bytes) or the more advanced ddtz.com (uses 2200h bytes). You can load files to the TPA (bank1) from 10400 to 1e200 (save.com) or 1c800 (if ddtz.com is loaded).
You can move Z80 bios code to bank1 to examinate with ddtz etc. and with the monitor x command you're back in CP/M (get a CP/M mem map to know what is used)

The attachment contains utils to assemble/debug the following source code plus a working binary (tedmon.com):
Code (tedmon.mac) Select

.RADIX 16 ;all # in hex
.Z80
ASEG
ORG 0100
;
BDOS   EQU    00005
;
  JP   START
;
BIOJMP:            ;BIOS CALL VIA JMP-TABLE  A = BIOS FN * 3
  PUSH HL
  LD   HL,(00001)
  LD   L,A
  EX   (SP),HL
  RET
;
FN30:
  JP   0F05A       ;XBIOS SUBFUNCTION CALL    A = SUB FN
;
CHARSET:           ;temp. copied to the end of the cpu switch routine
  PUSH BC          ;RESTORES 80COL CP/M CHARSET
  PUSH DE         
  CALL 005BD
  POP  DE
  POP  BC
  RET
;
START:
  LD   HL,(00001)      ;adjust XBIOS jmp addr.
  LD   L,5A
  LD   (FN30 + 1),HL
BUGFIX:                ;bugfix for version 85 bios
  LD   DE,0262B        ;bank0 addr.
  XOR  A               ;0=byte read fn to reg C
  CALL FN30
  LD   A,0C3           ;wrong opcode Z80 JMP instead of 8502 JMP($xxxx)
  XOR  C               ;compare
  JR   NZ,NOBUG        ;skip if not equal
  LD   C,06C           ;else load correct value to C
  INC  A               ;1=byte write fn from reg C
  CALL FN30
NOBUG:                 ;disable irq
  DI
  LD   BC,0D01A        ;temp save vic irq reg
  IN   A,(C)
  PUSH AF
  LD   BC,00001        ;B=dest. bank  C=src. bank
  LD   A,057           ;bios XMOVE
  CALL BIOJMP          ;set banks for the next move call
  LD   BC,00080        ;# byte count
  LD   DE,00180        ;src. addr.
  LD   HL,02A80        ;dest. addr.
  LD   (0FD05),HL      ;start addr. for the USR-Jump function
  LD   A,04B           ;bios MOVE
  CALL BIOJMP          ;copy the 8502 code block to bank0
  LD   BC,START - CHARSET
  LD   DE,0FFEE
  LD   HL,CHARSET
  LDIR                 ;temp copy charset reload call to the switch rout.
  LD   L,009           ;Bios8502 subfunction 9=USR-Jump via ($fd05)
  LD   A,004           ;XBIOS subfunction 4=call bios8502
  CALL FN30            ;execute custom 8502 code
  LD   A,0C9           ;restore default opcode (Z80 RET) in switch rout.
  LD   (0FFEE),A
  LD   BC,0D01A        ;restore vic irq reg
  POP  AF
  OUT  (C),A
  DEC  C
  OUT  (C),A           ;clear irq req. reg
  EI                   ;enable irq
  LD   E,01A           ;clr screen
  LD   C,002
  CALL BDOS
  JP   00000           ;return to CP/M
;
DS 80 - ($ AND 07F) ;align to record boundary
;
; the following code is transfered to bank0 at $2a80 before execution
;
DB  0A9,000      ;$2A80: LDA #$00   enable roms (bank15)
DB  08D,000,0FF  ;       STA $FF00
DB  0A9,004      ;       LDA #$04   set 1k common ram at $0000-$03ff
DB  08D,006,0D5  ;       STA $D506
DB  0A9,0C6      ;       LDA #$C6   new irq addr. ($2ac6)
DB  0A2,02A      ;       LDX #$2A
DB  08D,014,003  ;       STA $0314
DB  08E,015,003  ;       STX $0315
DB  0A9,0D2      ;       LDA #$D2   return addr. for monitor 'x' cmd ($2ad2)
DB  08D,000,00A  ;       STA $0A00
DB  08E,001,00A  ;       STX $0A01
DB  0A9,07F      ;       LDA #$7F   disable timer irq
DB  08D,00D,0DC  ;       STA $DC0D
DB  0AD,00D,0DC  ;       LDA $DC0D
DB  020,0B6,077  ;       JSR $77B6  fast mode on
DB  08D,012,0D0  ;       STA $D012  enable raster irq
DB  08D,01A,0D0  ;       STA $D01A
DB  0CE,019,0D0  ;       STA $D019
DB  024,0D7      ;       BIT $D7    80col active ?
DB  030,003      ;       BMI $2AB7  skip if yes
DB  020,05F,0FF  ;       JSR $FF5F  switch 40->80col
DB  020,062,0FF  ;$2AB7: JSR $FF62  load default vdc charset
DB  0AD,015,024  ;       LDA $2415  80col attribute (CP/M)
DB  085,0F1      ;       STA $F1
DB  020,042,0C1  ;       JSR $C142  editor init
DB  04C,000,0B0  ;       JMP $B000  start monitor
DB  000
;
DB  020,012,0C0  ;$2AC6: JSR $C012  keyboard scan
DB  020,03D,0F6  ;       JSR $F63D  run/stop key check
DB  0CE,019,0D0  ;       DEC $D019  clr raster irq
DB  04C,033,0FF  ;       JMP $FF33  end irq
;
DB  0A5,0D5      ;$2AD2: LDA $D5    wait until no key pressed
DB  049,058      ;       EOR #$58
DB  0D0,0FA      ;       BNE $2AD2
DB  078          ;       SEI
DB  08D,030,0D0  ;       STA $D030  slow mode
DB  08D,01A,0D0  ;       STA $D01A  disable raster irq
DB  085,09D      ;       STA $9D
DB  020,021,0CB  ;       JSR $CB21  cursor off
DB  0A9,00A      ;       LDA #$0A   set 4k common ram at $e000-$ffff
DB  08D,006,0D5  ;       STA $D506
DB  0AD,018,003  ;       LDA $0318  restore irq vector
DB  0AE,019,003  ;       LDX $0319
DB  08D,014,003  ;       STA $0314
DB  08E,015,003  ;       STX $0315
DB  08D,001,0FF  ;       STA $FF01  bank0 no rom
DB  0AD,0DE,0FF  ;       LDA $FFDE  hi byte of bios 8502 entry
DB  048          ;       PHA
DB  0A9,005      ;       LDA #$05   lo offset-1
DB  048          ;       PHA
DB  060          ;       RTS        return to bios
;
END


..LH
#3
CP/M / Easter Egg in CP/M mode (Z80 Rom)
June 08, 2010, 06:27 AM
Most of the old-schoolers know the following:

SYS 32800,123,45,6

... but while disassembling the Z80 rom I found a similar one available in CP/M too.
You can activate it with the following key sequence
(position cursor @ line 24 col 24 and do insert line):

<ESC>=88<ESC>e

looks like this:



the activation is hidden in the insert-line Rom-Bios function:


A052C:    ;FN 54 -print string (scrambled)
LD   HL,0FFFF
LD   (Y2404),HL
A0532:    ;FN 53 -print string DE=string adr
PUSH DE
A0533:
POP  HL
A0534:
LD   D,(HL)
INC  HL
LD   A,(Y2405)
AND  A
JR   Z,A0541
XOR  D
LD   (Y2405),A
LD   D,A
A0541:
LD   A,D
OR   A            ;chr 0 ?
RET  Z            ;yes, string end
CP   '$'          ;chr 36 ?
RET  Z            ;yes, string end
PUSH HL
LD   HL,A0533     ;continue adr.
PUSH HL
CP   00A          ;line feed
RET  Z            ;yes, get next chr
A054F:
CP   00D          ;return code
JR   NZ,A055E     ;skip if not
CALL A0A45        ;move to next line
CALL A06F1        ;40col
CALL A09F1
RST  018          ;80col
DB 00C            ;fn 6
;
...

A07DC:    ;FN 22 -insert line 80col
LD   DE,T0F62     ;addr. of the xor encrypted msg.
LD   A,017    ;cmp value 23d
LD   HL,(Y2413)
CP   H    ;line # in H
JP   Z,A0705
JR   C,A0804    ;skip if greater than 23d
LD   HL,006E0
LD   DE,00730
LD   B,018
A07F2:
CALL A080A
LD   A,(Y2414)
CP   B
JR   NZ,A07F2
CALL A0CC7
EX   DE,HL
LD   BC,00050
JR   A0841
;
A0804:
INC  A    ;A = 24d
CP   L    ;cmp. to col # in L
RET  NZ
JP   A052C    ;if equal jmp to $052c -> FN 54
...
;             scrambled text of soft- & hardware prod. team
T0F62:
DB 000,0F2,05B,039,001,04E,065,037,006,003,01E,007,00B,068,04B,034
DB 017,001,044,062,02D,018,012,00B,063,059,031,017,000,00B,059,072
DB 02B,018,00F,063,000,04F,02B,005,04C,068,02D,017,016,069,049,025
DB 017,013,045,068,029,018,017,007,00C,068,04B,034,013,00F,005,04B
DB 070,031,00D,00D,008,008,06C,00D
;