Patch a game from TAP to D64?

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Patch a game from TAP to D64?

Post by e5frog »

I got a request about Yleisurheilu (Athletic Game) for VIC-20 from a Finnish VIC-20 user.
Was mentioned here http://sleepingelephant.com/ipw-web/bul ... php?t=7275

I managed to rip the prg:s which is not that hard, save them to d64 and also patch the two first parts to load from device 8 instead of 1.

Unfortunately all the other files (loading to $2001) seem to be packed so they need to be unpacked, patched and possibly packed again. After loading from the first packed file it uses kernal (as the others did) to load the next file but reports 0 filename length - which I guess is no problem when loading from tape.
So even if "live patching" $BA to $08 instead of $01 - it reports file name missing as error, I guess if adding a proper name live it would load but the idea is to have it working from disk on a real machine.

Game is said to use 16K, I have added the d64 with what I have got so far, the last file (PADDLEN SAATO) is a separate file to be able to mark your paddles at a certain position to make it easier to play a certain game (I'm not Finnish speaking, google translate helps).

I will keep looking but it feels like I'm in over my head here, maybe someone could help and take this game to disk?

Amersoft and Logo have been patched on one byte to load from device 8 instead of 1.

It seems the depacking routine is at $5F80-$5FFF after loading a block at $2001.
Attachments
Partial_Patch_Yleisurheilu.zip
(45.96 KiB) Downloaded 55 times
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

The "START"-file has a LOAD statement in BASIC code - that's why I couldn't find it in the machine code.

Code: Select all

5 POKE45,PEEK(174):POKE46,PEEK(175):CLR
6 REM
10 SYS(256*(16*02+01)+16*05+07)
100 PRINT"{clear}{reverse on}** yleisurheilupeli **"
110 INPUT"{home}{down*3}montako kilpailijaa{space*3}{left*4}";N
130 IFN>60ORN<1THEN110
135 POKE5787,N
140 PRINT
145 FORL=1TON
150 PRINT"{down}kilpailija"L"{left}.";:INPUTNI$:NI$=LEFT$(NI$+"{space*6}",6)
155 FORK=1TO6
160 P$=MID$(NI$,K,1):P=ASC(P$)
165 POKE5788+6*L+K-7,P
170 NEXT:NEXT
180 FORI=0TO89
185 POKE38400+I,0
190 NEXT
195 LOAD
This is however packed and not just easily patchable.
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

Here's the BASIC code located at $2001 after unpacking for the second file JUO17:

Code: Select all

100 POKE45,PEEK(174):POKE46,PEEK(175):CLR
105 PRINTCHR$(31):POKE37139,128:POKE865,19:PO=36872:PA=37137
110 POKE36878,15:SYS5211:POKE177,0
125 REM ** JUO17
150 N=PEEK(5787)
155 DIMNI$(N),Q$(7),J(6),S(6),P(6)
160 FORI=1TO6:READP(I):J(I)=I:S(I)=I:NEXT
165 FORLL=1TON:FORI=0TO5
170 Z$=CHR$(PEEK(5788+6*LL+I-6)):NI$(LL)=NI$(LL)+Z$
175 NEXT:NEXT
180 NI$(0)="kiritt[j["
185 FORI=1TO7:READQ$(I):NEXT
190 POKE36879,25:Q1=3.67:Q2=2.62:Q3=400:Q4=100:Q5=.5:Q6=3600:Q7=60:H8=6.81:CA=127:CB=200
195 OI$="":FORI=1TO21:OI$=OI$+CHR$(29):NEXT
215 PRINTCHR$(31)+"{clear}{reverse on}{space*3}**{space*2}juoksu{space*2}**{space*5}"
220 FORI=1TO7
225 PRINT"{down}{right*6}"Q$(I):NEXT
230 PRINT"{down}{red}{right*3}uusi urh. laji{down*2}"+CHR$(31)
231 POKE867,255
232 Q=1+INT(PEEK(PO)/32):POKE866,1+2*Q:SYS5685
234 IFPEEK(PA)AND16THEN232
235 IFPEEK(PA)AND16THEN240
236 GOTO235
240 IFQ=8THENPRINT"{clear}{down*5}{space*5}odota hetki":PRINT"{down}{space*4}lataan kuulan":LOAD
245 S=1:H=5.76:F=.52:G=.47:IFQ=1THENM=1:P=4E-6:W=1280:H=4.7:F=4.8:G=F
250 IFQ=2THENM=1:P=35E-7:W=1525:F=3.66:G=3.61:X=253:Y=216:T=220:Z=30
255 IFQ=3THENM=1:P=3E-6:W=1563
260 IFQ=4THENM=1:S=2:P=25E-7:W=1685
265 IFQ=5THENM=2:S=3:P=23E-7:W=1185
270 IFQ=6THENM=8:S=4:P=22E-7:W=813
275 IFQ=7THENM=12:S=5:P=2E-6:W=875
280 FORLL=1TONSTEP2
300 U=0:U1=0:U2=0:Y1=0:Y2=0:N1=0:N2=0:P1=0:P2=0
305 J1=LL:J2=LL+1:IFJ2>NTHENJ2=0
310 IFRND(1)<.5THENJ=J1:J1=J2:J2=J
315 POKE36879,25:PRINT"{clear}{blue}{reverse on}**{space*2}juoksu "Q$(Q)"{space*2}**"
320 PRINT"{down*2}{space*3}sis[rata: "NI$(J1)
325 PRINT"{down}{space*3}ulkorata: "NI$(J2)
330 PRINT"{down*5}{space*3}paina nappia":GOSUB890
350 SYS5120
355 X=6:Y=7:GOSUB845:PRINTCHR$(5);"sis[{space*2}ulko":X=9:Y=13:GOSUB845:PRINT"aika"
360 K1=1:K2=1:J=88:A=73:B=69:AA=80:BB=95:V1=F:V2=G:FM=6.83:GM=6.78
362 IFQ=1THENA=87:AA=A:FM=6.74:GM=6.74:U1=0:U2=0
365 E1=1:E2=1:E3=2
370 GOTO515
395 FORR=0TO200:R0=PEEK(36872):R1=PEEK(36873):NEXT
400 IFR0*E1<30ANDR1*E2<30THEN450
405 GOSUB855:X=6:Y=2:GOSUB845:PRINT"varasl[ht{pound}"
410 IFR0>30THENY1=Y1+1:X=8:Y=9:GOSUB845:PRINT"v":IFY1=2THENN1=S:E1=0
415 IFR1>30THENY2=Y2+1:X=13:Y=9:GOSUB845:PRINT"v":IFY2=2THENN2=S:E2=0:E3=0
420 FORR=0TO4000:NEXT:X=6:Y=2:GOSUB845:PRINT"{space*10}":X=8:Y=9:GOSUB845:PRINT"{space*6}"
425 GOTO 395
450 GOSUB855:TI$="000000"
455 X=7:Y=9:GOSUB845:PRINTSTR$(S-N1):X=12:Y=9:GOSUB845:PRINTSTR$(S-N2)
460 MI=INT(TI*M/Q6):SE=INT(TI*M/Q7-Q7*MI)
465 X=8:Y=15:GOSUB845:PRINTRIGHT$("00"+MID$(STR$(MI),2),2)
470 X=11:Y=15:GOSUB845:PRINTRIGHT$("00"+MID$(STR$(SE),2),2)
475 R0=PEEK(36872):R1=PEEK(36873)
480 V1=V1+R0/W/(1+P1/Q4)*E1:V2=V2+R1/W/(1+P2/Q4)*E2:X=10:Y=15:GOSUB845:PRINT"."
485 X1=5:S1=32:IFR0>CB-P1*Q5THENX1=4:S1=122:K1=1.5
490 X2=5:S2=32:IFR1>CB-P2*Q5THENX2=4:S2=122:K2=1.5
495 K=CA-R0:P1=P1-P*K*K*K*K1:K1=1:IFP1<0THENP1=0
500 L=CA-R1:P2=P2-P*L*L*L*K2:K2=1:IFP2<0THENP2=0
505 POKE646,X1:X=8:Y=11:GOSUB845:PRINTCHR$(S1)
510 POKE646,X2:X=13:GOSUB845:PRINTCHR$(S2):POKE646,1
515 H1=J+SIN(V1)*A:H2=J+SIN(V2)*AA:I1=J+COS(V1)*B:I2=J+COS(V2)*BB
520 IFV1>Q2ANDV1<Q1THENI1=28
525 IFV2>Q2ANDV2<Q1THENI2=6
530 IFV1>HANDV1<H8THENI1=148
535 IFV2>HANDV2<H8THENI2=168
580 POKE167,H1:POKE168,I1:POKE165,H2:POKE166,I2
585 IFU=0THENU=1:SYS5222:GOTO395
590 SYS5574
592 IFV1>FMANDY1<3ANDU1=0THENV1=.55:N1=N1+1
593 IFV2>GMANDY2<3ANDU2=0THENV2=.50:N2=N2+1
595 IFP1>Q3ANDU1=0THENN1=S:E1=0
600 IFP2>Q3ANDU2=0THENN2=S:E2=0:E3=0
605 IFN1=SANDU1=0THEND1=TI*M*E1:U1=1:E1=0
610 IFN2=SANDU2=0THEND2=TI*M*E2:U2=1:E2=0
615 IFU1=1ANDU2=1THEN670
630 GOTO455
670 M1=INT(D1/Q6):O=D1/Q7-Q7*M1:S1=INT(O):T1=INT((O-S1)*Q4)
675 M2=INT(D2/Q6):O=D2/Q7-Q7*M2:S2=INT(O):T2=INT((O-S2)*Q4)
680 X=7:Y=2:GOSUB845:PRINT"loppuaika":X=7:Y=11:GOSUB845:PRINT"{space*7}"
685 X=9:Y=13:GOSUB845:PRINT"{space*4}":X=8:Y=15:GOSUB845:PRINT"{space*5}"
690 X=6:Y=7:GOSUB845:PRINT" sis[rata ":X=7:Y=12:GOSUB845:PRINT"ulkorata"
695 TU$(J1)=RIGHT$("00"+MID$(STR$(M1),2),2)
700 TU$(J2)=RIGHT$("00"+MID$(STR$(M2),2),2)
705 TU$(J1)=TU$(J1)+"."+RIGHT$("00"+MID$(STR$(S1),2),2)
710 TU$(J2)=TU$(J2)+"."+RIGHT$("00"+MID$(STR$(S2),2),2)
715 TU$(J1)=TU$(J1)+","+RIGHT$("00"+MID$(STR$(T1),2),2)
720 TU$(J2)=TU$(J2)+","+RIGHT$("00"+MID$(STR$(T2-E3),2),2)
725 X=7:Y=9:GOSUB845:PRINTTU$(J1)
730 Y=14:GOSUB845:PRINTTU$(J2)
735 X=5:Y=19:GOSUB845:PRINT"paina nappia"
740 SYS5300
745 GOSUB890
750 NEXT LL
770 POKE36879,25:PRINT"{clear}{blue}{reverse on}**{space*2}juoksu "Q$(Q)"{space*2}**"
775 PRINT"{down}{space*3}tulokset{space*14}{cm t*8}"
777 IFN=1THEN805
780 FORI=1TON-1
785 FORJ=ITON
790 IFTU$(J(I))="00.00,00"THENX=J(I):J(I)=J(J):J(J)=X:GOTO800
792 IFTU$(J(J))="00.00,00"THEN800
795 IFTU$(J(I))>TU$(J(J))THENX=J(I):J(I)=J(J):J(J)=X
800 NEXT:NEXT
801 FORI=1TON-1
802 IFTU$(J(I))=TU$(J(I+1))THENS(I+1)=S(I)
803 NEXT
805 FORI=1TON
810 PRINTMID$(STR$(S(I)),2)". "NI$(J(I))":"TU$(J(I));P(S(I))"{left}p."
815 POKE38393+6*Q+J(I),P(S(I))
820 NEXT
825 PRINT"{home}{down*22}{space*3}paina nappia{home}"
830 GOSUB890
835 RUN105
845 PRINT"{home}"+LEFT$(OI$,X)+LEFT$("{down*22}",Y);:RETURN
855 POKE36876,230:POKE36875,230
860 FOR I=1 TO 300
865 NEXT
870 POKE36876,0:POKE36875,0:RETURN
880 POKE37154,127:F0=(PEEK(37137)AND16):F1=(PEEK(37152)AND128):POKE37154,255
885 RETURN
890 GOSUB880:IFF0=0ORF1=0THEN890
892 FA=1:FB=1
893 GOSUB880
894 IFF0=0THENFA=0
895 IFF1=0THENFB=0
896 IFFAORFBTHEN893
905 GOSUB880:IFF0=0ORF1=0THEN905
910 RETURN
915 DATA7,5,4,3,2,1
920 DATA"{space*2}100 m","{space*2}200 m","{space*2}400 m","{space*2}800 m"," 1500 m"," 5000 m","10000 m"
There's the plain LOAD command on row 240.

So either it means manually patching the packed files so that they do something else instead of load or perhaps the LOAD command can be caught and redirected to some other code. Cassette buffer $033C-$03FB seems to be available, I wrote some code that will keep a variable with filename that is counted up for each use so if the load could be redirected it would be able to load files 0,1,2,...9 with that routine.

So what's needed to catch the LOAD-command made from BASIC?
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

After first loading the short autostarting program "AMERSOFT", the LOGO is loaded, this program puts some routines at $5F80 and redirects the LOAD vector (0330) to $5FC5. I think that's the spot to "attack" and change the load behaviour to load from disk instead.

I was thinking something like this:

Code: Select all

.LOAD
        LDA #$01        ; Filename length 1
        LDX #<.FNAME     ; LSB of filename string 
        LDY #>.FNAME     ; MSB if filename string
        JSR $FFBD       ; Filename to kernal
        INC .FNAME       ; Increases filename to next in line

        LDA #$01
        LDX #$08
        LDY #$01        ; Secondary address = load to header address 
        JSR $FFBA       ; Set logical filename parameters
                        ; A=file number, X=device, Y=command

etc etc


.FNAME
        BYTE    $41     ; Name of first file is A, then increased (10 files)

Here's what the LOAD vector does:

Code: Select all

.C:5fc5  85 93       STA $93          ; 0 load, 1 verify
.C:5fc7  C9 00       CMP #$00 
.C:5fc9  D0 0C       BNE $5FD7
.C:5fcb  A5 B9       LDA $B9          ; Fetch current secondary address 
.C:5fcd  D0 08       BNE $5FD7        ; Branch if not zero
.C:5fcf  C4 2C       CPY $2C          ; Compare Y with $2C, start of BASIC
.C:5fd1  D0 04       BNE $5FD7        ; Branch if not zero
.C:5fd3  E4 2B       CPX $2B          ; Compare X with $2B, start of BASIC
.C:5fd5  F0 03       BEQ $5FDA        ; Subroutine jump i same
.C:5fd7  4C 4B F5    JMP $F54B        ; Jump to Kernal routine

.C:5fda  20 4B F5    JSR $F54B

.C:5fdd  08          PHP
.C:5fde  48          PHA
.C:5fdf  A5 2B       LDA $2B
.C:5fe1  85 FB       STA $FB
.C:5fe3  A5 2C       LDA $2C
.C:5fe5  85 FC       STA $FC
.C:5fe7  A0 00       LDY #$00
.C:5fe9  98          TYA
.C:5fea  51 FB       EOR ($FB),Y
.C:5fec  91 FB       STA ($FB),Y
.C:5fee  C8          INY
.C:5fef  D0 F8       BNE $5FE9
.C:5ff1  E6 FC       INC $FC
.C:5ff3  A5 AF       LDA $AF
.C:5ff5  C5 FC       CMP $FC
.C:5ff7  B0 F0       BCS $5FE9
.C:5ff9  A6 AE       LDX $AE
.C:5ffb  A4 AF       LDY $AF
.C:5ffd  68          PLA
.C:5ffe  28          PLP
.C:5fff  60          RTS
My other interest: http://channelf.se
Vic Porter
Vic 20 Amateur
Posts: 61
Joined: Thu Sep 22, 2016 9:12 pm
Occupation: VIC porter

Re: Patch a game from TAP to D64?

Post by Vic Porter »

The LOAD replacement seems to EOR every byte with the previous one, with the initial previous value of the load destination MSB and new seed taken from $AF every $100 bytes. Some copy protection scheme? Without looking at the actual files, it seems that fixing the EOR'd files should be simple enough and a plain LOAD would work.
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

This seems to be the part that unpacks the loaded data, it returns here if a load through subroutine is made - which it does if it loads data to the same start address. From what I can see all files load to $2001.

Code: Select all

12d0 20 4b f5 jsr $f54b	; Kernal load routine

12d3 08       php 		; Push to stack
12d4 48       pha 
12d5 a5 2b    lda $2b           ; Start of BASIC
12d7 85 fb    sta $fb           ; Store start of BASIC in FB
12d9 a5 2c    lda $2c           ; Start of BASIC
12db 85 fc    sta $fc           ; Store start of BASIC in FC
12dd a0 00    ldy #$00

12df 98       tya 			; Unpacking routine? 
12e0 51 fb    eor ($fb),y
12e2 91 fb    sta ($fb),y
12e4 c8       iny 
12e5 d0 f8    bne $12df
12e7 e6 fc    inc $fc
12e9 a5 af    lda $af
12eb c5 fc    cmp $fc
12ed b0 f0    bcs $12df

12ef a6 ae    ldx $ae		; Tape end addresses (end of program) in X and Y
12f1 a4 af    ldy $af
12f3 68       pla 			; restore from stack
12f4 28       plp 
12f5 60       rts 

; end of routine copied to 5F7A-5FFF 

So it seems it just does exor with 0 then 1 with the next byte and so on until it rolls over and starts from 0 again. The tape end addresses are needed, I don't know if something similar is available when loading from disk.

I got all of the parts decoded, seems most are plain basic and some have some extra data at the end, it will be easier to make a translation though.
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

I patched out the decoding process with NOP:s in LOGO and tried a round with the decoded prg:s in a T64 - seemed to work just fine.

It's now in a state where it can easily be translated from Finnish - but we're still stuck with tape for now.
Yleisurheilu_no_decode.zip
(21.38 KiB) Downloaded 83 times
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

Turns out it was easiest to edit the BASIC-part in the events to load next part from disk (with filename) instead of just "LOAD". Which meant some copy and paste, edit in CBM prg Studio, compile and copy and past again, for each file.

Seems to work OK, but it crashes when you get to the end and try to start from the beginning - which is done by loading the first file (Short file to 02A7). When doing that or when loading the logo, not sure, it hangs with CPU jam. Maybe it needs some extra settings (pokes/sys) when handling that, will look into it - maybe it will work anyway on a real machine...

It's not hard to restart simply by selecting the quit option and the reload from start though.

If selecting the option to start from the first event it seems to work just fine - same players I guess, perhaps it will work to load the START-file instead of starting from the first file.

Beta of Yleisurheilu for VIC-20 as disk image included...
Enable paddle and pay with your mouse in WinVICE, I'm not sure how to play - maybe someone's got instructions?

I'm considering a translation as well, there's some interesting animations in the game.

*phew*
Yleisurheilu beta 1.zip
(24.18 KiB) Downloaded 55 times
Start with LOAD"*",8,1 after activating 16K extra RAM
Last edited by e5frog on Fri Nov 04, 2016 9:34 am, edited 1 time in total.
My other interest: http://channelf.se
User avatar
mrr19121970
Vic 20 Nerd
Posts: 873
Joined: Tue Jan 19, 2016 9:22 am
Location: Germany
Occupation: IT service manager

Re: Patch a game from TAP to D64?

Post by mrr19121970 »

It didn't work at all for me in VICE

Update


Helps to turn on 16k expansion
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

I changed the loading on the last file to load START file instead of starting with the first file - as it didn't work. So you can set up a new game without loading from scratch.

Please try it out and report any problems.

I started translating, noticed there are instructions for a few events, not sure that's ever shown - or if it's even for VIC-20...
Attachments
Yleisurheilu beta 2.zip
(24.34 KiB) Downloaded 49 times
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

It's possible 8K works as well... not sure.

I finished the English version, I think it's pretty OK, don't mind feedback about it.

So, stuff your extra ram in (16K), plug your paddles in your VIC (ALT+Q to use mouse as paddle in WinVICE) and why not start off with the "adjust paddles" program to get the setting exactly right.
Boot game with LOAD"*",8,1

Afaik the whole game runs with paddles apart from entering 1-6 competitors on the start part.


Fresh from the harddrive - ENGLISH VERSION!
(The above large text is a link.)

Many thanks to software programmers of TAPclean, WinVICE, WinHEX, DirMaster and CBM prg Studio
My other interest: http://channelf.se
User avatar
e5frog
Vic 20 Nerd
Posts: 551
Joined: Sat Feb 17, 2007 5:46 pm
Website: http://channelf.se
Location: Sweden
Occupation: Service Engineer

Re: Patch a game from TAP to D64?

Post by e5frog »

Latest edition, double languages, some corrections made, removed an original bug regarding number of players.
Attachments
Yleisurheilu X2.zip
(33.84 KiB) Downloaded 175 times
My other interest: http://channelf.se
Post Reply