Reputation: 210
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
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
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