Peatherfed
Peatherfed

Reputation: 210

Using xa65 to create a Commodore 64 .prg file and disk image

I've tried looking at Using xa65 assembler to create Commodore 64 .prg but I couldn't get the examples to work.

I'm using the VICE emulator.

So my super basic assembly program looks like this:

.byte $01, $08
lda #1
sta $0400
jmp $0801

and checking a hexdump after assembling confirms that it is correctly assembled. As far as I can find online, this should be enough for a usable .prg file. However, if I try to use VICE's "Autostart" feature, it doesn't work. So I tried creating a disk image using c1541 with the following command:

c1541 -format diskname,id d64 my_diskimage.d64 -attach my_diskimage.d64 -write my_program.prg myprog

and while I can create a disk image, and attach it to drive #8, running LOAD "*",8,1 doesn't work. It simply gets stuck on the loading.

I have no idea where I'm going wrong. I thought the 2-byte header followed by the binary data would be enough, and that after loading I could simply launch the program by typing SYS 2049.

I'd like to resolve this obviously, but I'm also curious as to why

  1. VICE's autostart failed.
  2. The disk image loading gets stuck.

EDIT: I tried manually poking in the outputted values into $c000 and doing a sys call, but that didn't work either! Now I'm really confused. What I did was:

POKE 49152, 1
POKE 49153, 169

POKE 49154, 0
POKE 49155, 141

POKE 49156, 76
POKE 49157, 4

POKE 49158, 192
POKE 49159, 0

SYS 49152

For reference, the hexdump of the .prg file is

c000 01a9 008d 4c04 c000

Of course, with my pokes I ignored the first $c000, since that's just the .prg header.

Upvotes: 4

Views: 271

Answers (1)

Omar and Lorraine
Omar and Lorraine

Reputation: 1266

POKE 49152, 1
POKE 49153, 169

POKE 49154, 0
POKE 49155, 141

POKE 49156, 76
POKE 49157, 4

POKE 49158, 192
POKE 49159, 0

What we've got wrong here is the endianness. Each byte is pairwise reversed. So that program disassembles to:

    ora (a9),x
    brk
    sta $044c
    cpy #$00

Okay, so each one of your instructions has been mutated to something completely different from what you intended bbecause the bytes have been swapped round.

  • a901 is lda #1
  • 01a9 is ora (a9),x

For this reason, your program starting at address 49152 decimal also does not end in a rts or jmp instruction, so I'm expecting it to crash your Commodore 64.

while I can create a disk image, and attach it to drive #8, running LOAD "*",8,1 doesn't work. It simply gets stuck on the loading.

When you do LOAD "*",8,1, the operating system ignores the header telling the computer where in memory to load the file. It will load the file to wherever BASIC starts, which varies from model to model (the VIC-20 and the PETs have BASIC programs starting at different addresses).

So the ,1 at the end of that command also means that this is a BASIC program, so BASIC will try to interpret your program (it will fail; this is not a BASIC program; it's machine code).

This is why your autostart is failing.

My best guess is that the file loads okay though. You can check in VICE's excellent debugger.

What I've got in my game to get autostart working is to put code at the start of the file which BASIC can interpret. Doesn't have to be much; just a simple line like 10 SYS 1234, which will invoke the machine code program at that address. Then later in the binary, we can stick our machine code at the same address. But obviously we can get the assembler to figure out the entrypoint's address for us. So something like:

; The following is a short BASIC program
; 10 SYS 1234
; and causes the machine to jump to the machine code starting at init_entrypoint

* = $0801
    ; line number and SYS token
    .byte $0C, $08, $0A, $00, $9E, $20

    ; what's the address of the routine in decimal
    .byte $30 + ((init_entrypoint) / 1000)
    .byte $30 + ((init_entrypoint % 1000) / 100)
    .byte $30 + ((init_entrypoint % 100) / 10)
    .byte $30 + ((init_entrypoint % 10))

     ; null terminate the BASIC program
    .byte $00, $00, $00

init_entrypoint: ; here's your program OP
    lda #1
    sta $0400
    jmp init_entrypoint

This assembles to valid BASIC (or at least, it did when I built it last!), and can be RUN, LISTed, autostarted, etc. You might have to make adjustments if you want to use xa65.

Upvotes: 2

Related Questions