Skip to content

Commit

Permalink
Initial version.
Browse files Browse the repository at this point in the history
  • Loading branch information
dmsc committed Jun 13, 2016
0 parents commit 17f9b94
Show file tree
Hide file tree
Showing 21 changed files with 2,153 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
obj/
mkatr
339 changes: 339 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#
# Copyright (C) 2016 Daniel Serpell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>
#

SOURCES=\
crc32.c\
darray.c\
flist.c\
mkatr.c\
msg.c\
spartafs.c\

CFLAGS=-O2 -Wall
LDFLAGS=

BUILD_DIR=obj
OBJS=$(addprefix $(BUILD_DIR)/,$(SOURCES:%.c=%.o))
DEPS=$(OBJS:%.o=%.d)

all: mkatr


clean:
-rm -f $(OBJS) $(DEPS)
-rmdir $(BUILD_DIR)

# Create output dirs
$(BUILD_DIR):
mkdir -p $@

$(OBJS): | $(BUILD_DIR)
$(DEPS): | $(BUILD_DIR)

# Compilation
$(BUILD_DIR)/%.o: src/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<

# Link
mkatr: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@

# Dependencies
$(BUILD_DIR)/%.d: src/%.c
$(CC) -MM -MP -MF $@ -MT "$(@:.d=.o) $@" $(CFLAGS) $(CPPFLAGS) $<

ifneq "$(MAKECMDGOALS)" "clean"
ifneq "$(MAKECMDGOALS)" "distclean"
-include $(DEPS)
endif
endif
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
ATR disk image creation tool
----------------------------

This program creates Atari `ATR` disk images from a list of files given
in the command line, in the SpartaDOS / BW-DOS disk format.

Program Usage
-------------

mkatr [options] output filenames

Options:

- `-h` Shows a brief help

- `-b` Selects the next file in the command line as the _boot_ file,
the file will be loaded when the computer boots, and must be
in the standard Atari binary file format.

To place files inside a sub-directory, simply add the directory *before*
all the files inside that directory.

Usage Examples
--------------

To create an image named `disk1.atr` with all the files in the "atari"
directory:

mkatr disk1.atr atari/*

To create a bootable BW-DOS image with the DOS files inside a
subdirectory and a startup.bat file outside:

mkatr bwdos.atr dos/ -b dos/xbw130.dos startup.bat

To create an image with only one file that will be loaded at boot:

mkatr game.atr -b mygame.com


Compilation
-----------

Compile with `make` and copy the resulting `mkatr` program to your bin
folder.

269 changes: 269 additions & 0 deletions src/asm/boot128.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
; Bootloader for 128byte sectors
;
opt h-

DATA_INDEX equ $0043
MAP_INDEX equ $0044
IO_ADDRESS equ $0045
IO_LENGTH equ $0047
PTR equ $0049

RUNAD equ $02E0
INITAD equ $02E2
DCB equ $0300
ICCOM equ $0342
ICSTA equ $0343
ICBAL equ $0344
ICBAH equ $0345
ICBLL equ $0348
ICBLH equ $0349
ICAX1 equ $034A
ICAX2 equ $034B
CIOV equ $E456
SIOV equ $E459


; Specify BASE_ADDRESS in command line, as -d:BASE_ADDRESS=\$2100
;BASE_ADDRESS equ $2000

MAP_BUFFER equ BASE_ADDRESS
DATA_BUFFER equ BASE_ADDRESS + $80
LOAD_ADDRESS equ BASE_ADDRESS + $100

org LOAD_ADDRESS

.byte 0
.byte 3 ; Number of sectors to load
.word LOAD_ADDRESS ; Load address
.word $0000
jmp START ; Jump to START (must be XX80 for SDX compatibility)

.word $0000 ; MAIN DIR MAP SECTOR
.word $0000 ; MAX SECTOR
.word $0000 ; FREE SECTORS
.byte $00 ; SECTORS PER BITMAP
.word $0000 ; BITMAP START SECTOR
.word $0000 ; LAST ALLOCATED FILE SECTOR
.word $0000 ; LAST ALLOCATED DIR SECTOR
.byte 'DSKLABEL' ; DISK LABEL
.byte 40 ; NUMBER OF TRACKS
.byte $80 ; SECTOR SIZE
.byte $20 ; DISK FORMAT VERSION (2.0)
.byte $00,$00,$00,$00,$00 ; RESERVED
.byte $00 ; DISK SEQ NUMBER
.byte $00 ; DISK RANDOM ID
BOOT_MAP:
.word $0000 ; BOOT FILE MAP SECTOR
.byte $00,$00,$00,$00,$00,$00 ; RESERVED

ERROR_MSG:
.byte 'DOS Error', $9B
ERROR_MSG_LEN equ * - ERROR_MSG

SIO_READ_BUF:
.if >MAP_BUFFER != >DATA_BUFFER
.error "Error, MAP_BUFFER and DATA_BUFFER must be on same page"
.endif
ldx #>MAP_BUFFER

SIO_READ:
sty DCB+4 ; Store address
stx DCB+5
sta DCB+10 ; Store and check sector number
ora DCB+11
beq READ_BLANK ; If sector == 0, read zeroes
lda #$40
sta DCB+3
jsr SIOV
bpl RTS_OK

DOS_ERROR:
lda #<ERROR_MSG
sta ICBAL
.if <ERROR_MSG < ERROR_MSG_LEN
.error "Error, low byte of message address should be bigger than message length"
.endif
sta ICBLL
lda #>ERROR_MSG
sta ICBAH
lda #$09
sta ICCOM
ldx #$00
jsr CIOV
@loop: jmp @loop

READ_BLANK:
stx PTR+1 ; Store destination address
sty PTR
tay ; A is already 0
@copy:
sta (PTR),y
iny
bpl @copy
RTS_OK:
rts

GO_INITAD:
jmp (INITAD)

END_LOAD:
jmp (RUNAD)

; START must be at $XX80
.align $80, $ea
.if START != LOAD_ADDRESS + $80
.error "Error, START symbol must be at $XX80, currently at ", START
.endif
START:
; Set index to end of sector data
lda #$80
sta MAP_INDEX
sta DATA_INDEX
; Set read size to sector size
sta DCB+8
asl
sta DCB+9

; Read binary header: "FF FF"
jsr GET_2_BYTES
inx
bne DOS_ERROR
cmp #$FF
bne DOS_ERROR

; Read first address, copy to RUNAD
jsr GET_2_BYTES
sta RUNAD
stx RUNAD+1
jmp FIRST_SEG

; Reads a data block
READ_DATA_BLOCK:
; Get start address
jsr GET_2_BYTES
FIRST_SEG:
sta IO_ADDRESS
stx IO_ADDRESS+1
ora IO_ADDRESS+1
beq END_LOAD

; Skip $FFFF header in the middle of file
txa
and IO_ADDRESS
cmp #$FF
beq READ_DATA_BLOCK

; Get end address
jsr GET_2_BYTES
sec
sbc IO_ADDRESS
sta IO_LENGTH
txa
sbc IO_ADDRESS+1
sta IO_LENGTH+1

; Setup INITAD to an "rts" instruction.
lda #<RTS_OK
sta INITAD
lda #>RTS_OK
sta INITAD+1

; Read data
jsr GET_DATA
; Execute INITAD
jsr GO_INITAD
; GO to next block
jmp READ_DATA_BLOCK

GET_2_BYTES:
jsr GET_BYTE
pha
jsr GET_BYTE
tax
pla
rts


DEC_IO_LENGTH_1:
dec IO_LENGTH+1
DEC_IO_LENGTH:
dec IO_LENGTH

GET_DATA:
jsr GET_BYTES
ldy #$00
sta (IO_ADDRESS),y
inc IO_ADDRESS
bne @skip
inc IO_ADDRESS+1
@skip: lda IO_LENGTH
bne DEC_IO_LENGTH
lda IO_LENGTH+1
bne DEC_IO_LENGTH_1
rts

GET_BYTE:
lda #$00
sta IO_LENGTH+1
sta IO_LENGTH
GET_BYTES:
ldx DATA_INDEX
bmi NEXT_SECTOR
GET_BYTE_X:
lda DATA_BUFFER,x
inx
stx DATA_INDEX
rts

GET_FULL_SECTOR:
ldy IO_ADDRESS
ldx IO_ADDRESS+1
jsr SIO_READ
lda IO_ADDRESS
eor #$80
sta IO_ADDRESS
bmi @skip1
inc IO_ADDRESS+1
@skip1:
lda IO_LENGTH
eor #$80
sta IO_LENGTH
bpl @skip2
dec IO_LENGTH+1
@skip2:
; Fall through
;;; jmp NEXT_SECTOR

NEXT_SECTOR:
ldy MAP_INDEX
bmi NEXT_MAP
NEXT_SECTOR_Y:
lda MAP_BUFFER,y
ldx MAP_BUFFER+1,y
stx DCB+11
iny
iny
sty MAP_INDEX

ldy IO_LENGTH+1
bne GET_FULL_SECTOR
ldy IO_LENGTH
bmi GET_FULL_SECTOR
ldy #<DATA_BUFFER
jsr SIO_READ_BUF
ldx #0
beq GET_BYTE_X

NEXT_MAP:
lda BOOT_MAP
ldx BOOT_MAP+1
stx DCB+11
ldy #<MAP_BUFFER
jsr SIO_READ_BUF
lda MAP_BUFFER
sta BOOT_MAP
lda MAP_BUFFER+1
sta BOOT_MAP+1
ldy #$04
bne NEXT_SECTOR_Y

Loading

0 comments on commit 17f9b94

Please sign in to comment.