mirror of
https://github.com/mi57730/a2d.git
synced 2024-11-29 07:49:20 +00:00
724 lines
18 KiB
ArmAsm
724 lines
18 KiB
ArmAsm
.setcpu "65C02"
|
|
|
|
.include "apple2.inc"
|
|
.include "../inc/apple2.inc"
|
|
.include "../inc/prodos.inc"
|
|
.include "../mgtk.inc"
|
|
.include "../desktop.inc"
|
|
.include "../macros.inc"
|
|
|
|
;;; ============================================================
|
|
;;; Memory map
|
|
;;;
|
|
;;; Main Aux
|
|
;;; : : : :
|
|
;;; | | | |
|
|
;;; | DHR | | DHR |
|
|
;;; $2000 +-----------+ +-----------+
|
|
;;; | IO Buffer | |Win Tables |
|
|
;;; $1C00 +-----------+ | |
|
|
;;; $1B00 | | +-----------+
|
|
;;; | | | |
|
|
;;; | | | |
|
|
;;; | MP Dst | | MP Dst |
|
|
;;; $1580 +-----------+ +-----------+
|
|
;;; | | | |
|
|
;;; | MP Src | | |
|
|
;;; $1100 +-----------+ +-----------+
|
|
;;; | | | |
|
|
;;; | DA | | DA (Copy) |
|
|
;;; $800 +-----------+ +-----------+
|
|
;;; : : : :
|
|
;;;
|
|
|
|
hires := $2000 ; HR/DHR images are loaded directly into screen buffer
|
|
hires_size = $2000
|
|
|
|
;; Minipix/Print Shop images are loaded/converted
|
|
minipix_src_buf = $1200 ; Load address
|
|
minipix_src_size = 576
|
|
minipix_dst_buf = $1580 ; Convert address
|
|
minipix_dst_size = 26*52
|
|
|
|
.assert (minipix_src_buf + minipix_src_size) < minipix_dst_buf, error, "Not enough room for Minipix load buffer"
|
|
.assert (minipix_dst_buf + minipix_dst_size) < WINDOW_ICON_TABLES, error, "Not enough room for Minipix convert buffer"
|
|
|
|
;;; ============================================================
|
|
|
|
.org $800
|
|
|
|
da_start:
|
|
jmp start
|
|
|
|
save_stack:.byte 0
|
|
|
|
.proc start
|
|
tsx
|
|
stx save_stack
|
|
|
|
;; Copy DA to AUX
|
|
copy16 #da_start, STARTLO
|
|
copy16 #da_start, DESTINATIONLO
|
|
copy16 #da_end, ENDLO
|
|
sec ; main>aux
|
|
jsr AUXMOVE
|
|
|
|
;; Transfer control to aux
|
|
sta RAMWRTON
|
|
sta RAMRDON
|
|
|
|
;; Copy "call_main_template" routine to zero page
|
|
COPY_BYTES sizeof_routine+1, routine, call_main_trampoline
|
|
|
|
;; run the DA
|
|
jsr init
|
|
|
|
;; tear down/exit
|
|
sta RAMRDOFF
|
|
sta RAMWRTOFF
|
|
|
|
ldx save_stack
|
|
txs
|
|
|
|
rts
|
|
.endproc
|
|
|
|
call_main_trampoline := $20 ; installed on ZP, turns off auxmem and calls...
|
|
call_main_addr := call_main_trampoline+7 ; address patched in here
|
|
|
|
.proc routine
|
|
sta RAMRDOFF
|
|
sta RAMWRTOFF
|
|
jsr $1000 ; overwritten (in zp version)
|
|
sta RAMRDON
|
|
sta RAMWRTON
|
|
rts
|
|
.endproc
|
|
sizeof_routine = * - routine ; can't .sizeof(proc) before declaration
|
|
;; https://github.com/cc65/cc
|
|
|
|
;;; ============================================================
|
|
;;; ProDOS MLI calls
|
|
|
|
.proc open_file
|
|
jsr copy_params_aux_to_main
|
|
sta ALTZPOFF
|
|
MLI_CALL OPEN, open_params
|
|
sta ALTZPON
|
|
jsr copy_params_main_to_aux
|
|
rts
|
|
.endproc
|
|
|
|
.proc get_file_eof
|
|
jsr copy_params_aux_to_main
|
|
sta ALTZPOFF
|
|
MLI_CALL GET_EOF, get_eof_params
|
|
sta ALTZPON
|
|
jsr copy_params_main_to_aux
|
|
rts
|
|
.endproc
|
|
|
|
.proc read_file
|
|
jsr copy_params_aux_to_main
|
|
sta ALTZPOFF
|
|
MLI_CALL READ, read_params
|
|
sta ALTZPON
|
|
jsr copy_params_main_to_aux
|
|
rts
|
|
.endproc
|
|
|
|
.proc read_minipix_file
|
|
jsr copy_params_aux_to_main
|
|
sta ALTZPOFF
|
|
MLI_CALL READ, read_minipix_params
|
|
sta ALTZPON
|
|
jsr copy_params_main_to_aux
|
|
rts
|
|
.endproc
|
|
|
|
.proc close_file
|
|
jsr copy_params_aux_to_main
|
|
sta ALTZPOFF
|
|
MLI_CALL CLOSE, close_params
|
|
sta ALTZPON
|
|
jsr copy_params_main_to_aux
|
|
rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
;;; Copies param blocks from Aux to Main
|
|
.proc copy_params_aux_to_main
|
|
ldy #(params_end - params_start + 1)
|
|
sta RAMWRTOFF
|
|
loop: lda params_start - 1,y
|
|
sta params_start - 1,y
|
|
dey
|
|
bne loop
|
|
sta RAMRDOFF
|
|
rts
|
|
.endproc
|
|
|
|
;;; Copies param blocks from Main to Aux
|
|
.proc copy_params_main_to_aux
|
|
pha
|
|
php
|
|
sta RAMWRTON
|
|
ldy #(params_end - params_start + 1)
|
|
loop: lda params_start - 1,y
|
|
sta params_start - 1,y
|
|
dey
|
|
bne loop
|
|
sta RAMRDON
|
|
plp
|
|
pla
|
|
rts
|
|
.endproc
|
|
|
|
params_start:
|
|
;;; This block gets copied between main/aux
|
|
|
|
;;; ProDOS MLI param blocks
|
|
|
|
DEFINE_OPEN_PARAMS open_params, pathbuff, DA_IO_BUFFER
|
|
DEFINE_GET_EOF_PARAMS get_eof_params
|
|
|
|
DEFINE_READ_PARAMS read_params, hires, hires_size
|
|
DEFINE_READ_PARAMS read_minipix_params, minipix_src_buf, minipix_src_size
|
|
|
|
DEFINE_CLOSE_PARAMS close_params
|
|
|
|
.proc pathbuff ; 1st byte is length, rest is full path
|
|
length: .byte $00
|
|
data: .res 64, 0
|
|
.endproc
|
|
|
|
|
|
params_end:
|
|
;;; ----------------------------------------
|
|
|
|
da_window_id = 100
|
|
|
|
.proc line_pos
|
|
left: .word 0
|
|
base: .word 0
|
|
.endproc
|
|
|
|
|
|
event_params: .tag MGTK::Event
|
|
|
|
.proc window_title
|
|
.byte 0 ; length
|
|
.endproc
|
|
|
|
.proc winfo
|
|
window_id: .byte da_window_id ; window identifier
|
|
options: .byte MGTK::Option::dialog_box
|
|
title: .addr window_title
|
|
hscroll:.byte MGTK::Scroll::option_none
|
|
vscroll:.byte MGTK::Scroll::option_none
|
|
hthumbmax: .byte 32
|
|
hthumbpos: .byte 0
|
|
vthumbmax: .byte 32
|
|
vthumbpos: .byte 0
|
|
status: .byte 0
|
|
reserved: .byte 0
|
|
mincontwidth: .word screen_width
|
|
mincontlength: .word screen_height
|
|
maxcontwidth: .word screen_width
|
|
maxcontlength: .word screen_height
|
|
|
|
.proc port
|
|
viewloc: DEFINE_POINT 0, 0
|
|
mapbits: .addr MGTK::screen_mapbits
|
|
mapwidth: .word MGTK::screen_mapwidth
|
|
maprect: DEFINE_RECT 0, 0, screen_width, screen_height
|
|
.endproc
|
|
|
|
pattern:.res 8, 0
|
|
colormasks: .byte MGTK::colormask_and, MGTK::colormask_or
|
|
penloc: DEFINE_POINT 0, 0
|
|
penwidth: .byte 1
|
|
penheight: .byte 1
|
|
penmode: .byte MGTK::notpencopy
|
|
textback: .byte $7F
|
|
textfont: .addr DEFAULT_FONT
|
|
nextwinfo: .addr 0
|
|
.endproc
|
|
|
|
|
|
.proc init
|
|
copy #0, mode
|
|
|
|
;; Get filename by checking DeskTop selected window/icon
|
|
|
|
;; Check that an icon is selected
|
|
copy #0, pathbuff::length
|
|
lda selected_file_count
|
|
beq abort ; some file properties?
|
|
lda path_index ; prefix index in table
|
|
bne :+
|
|
abort: rts
|
|
|
|
;; Copy path (prefix) into pathbuff buffer.
|
|
: src := $06
|
|
dst := $08
|
|
|
|
asl a ; (since address table is 2 bytes wide)
|
|
tax
|
|
copy16 path_table,x, src
|
|
ldy #0
|
|
lda (src),y
|
|
tax
|
|
inc src
|
|
bne :+
|
|
inc src+1
|
|
: copy16 #(pathbuff::data), dst
|
|
jsr copy_pathbuff ; copy x bytes (src) to (dst)
|
|
|
|
;; Append separator.
|
|
lda #'/'
|
|
ldy #0
|
|
sta (dst),y
|
|
inc pathbuff::length
|
|
inc dst
|
|
bne :+
|
|
inc dst+1
|
|
|
|
;; Get file entry.
|
|
: lda selected_file_list ; file index in table
|
|
asl a ; (since table is 2 bytes wide)
|
|
tax
|
|
copy16 file_table,x, src
|
|
|
|
;; Exit if a directory.
|
|
ldy #2 ; 2nd byte of entry
|
|
lda (src),y
|
|
and #$70 ; check that one of bits 4,5,6 is set ???
|
|
;; some vague patterns, but unclear
|
|
;; basic = $32,$33, text = $52, sys = $11,$14,??, bin = $23,$24,$33
|
|
;; dir = $01 (so not shown)
|
|
bne :+
|
|
rts ; abort ???
|
|
|
|
;; Append filename to path.
|
|
: ldy #9
|
|
lda (src),y ; grab length
|
|
tax ; name has spaces before/after
|
|
dex ; so subtract 2 to get actual length
|
|
dex
|
|
clc
|
|
lda src
|
|
adc #11 ; 9 = length, 10 = space, 11 = name
|
|
sta src
|
|
bcc :+
|
|
inc src+1
|
|
: jsr copy_pathbuff ; copy x bytes (src) to (dst)
|
|
|
|
jmp open_file_and_init_window
|
|
|
|
.proc copy_pathbuff ; copy x bytes from src to dst
|
|
ldy #0 ; incrementing path length and dst
|
|
loop: lda (src),y
|
|
sta (dst),y
|
|
iny
|
|
inc pathbuff::length
|
|
dex
|
|
bne loop
|
|
tya
|
|
clc
|
|
adc dst
|
|
sta dst
|
|
bcc end
|
|
inc dst+1
|
|
end: rts
|
|
.endproc
|
|
|
|
.endproc
|
|
|
|
.proc open_file_and_init_window
|
|
jsr open_file
|
|
lda open_params::ref_num
|
|
sta get_eof_params::ref_num
|
|
sta read_params::ref_num
|
|
sta read_minipix_params::ref_num
|
|
sta close_params::ref_num
|
|
|
|
MGTK_CALL MGTK::HideCursor
|
|
MGTK_CALL MGTK::OpenWindow, winfo
|
|
MGTK_CALL MGTK::SetPort, winfo::port
|
|
jsr set_color_mode
|
|
jsr show_file
|
|
MGTK_CALL MGTK::ShowCursor
|
|
|
|
MGTK_CALL MGTK::FlushEvents
|
|
MGTK_CALL MGTK::ObscureCursor
|
|
|
|
;; fall through
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Main Input Loop
|
|
|
|
.proc input_loop
|
|
MGTK_CALL MGTK::GetEvent, event_params
|
|
lda event_params + MGTK::Event::kind
|
|
cmp #MGTK::EventKind::button_down ; was clicked?
|
|
beq exit
|
|
cmp #MGTK::EventKind::key_down ; any key?
|
|
beq on_key
|
|
bne input_loop
|
|
|
|
on_key:
|
|
lda event_params + MGTK::Event::modifiers
|
|
bne input_loop
|
|
lda event_params + MGTK::Event::key
|
|
cmp #CHAR_ESCAPE
|
|
beq exit
|
|
cmp #' '
|
|
bne :+
|
|
jsr toggle_mode
|
|
: jmp input_loop
|
|
|
|
exit:
|
|
jsr set_bw_mode
|
|
MGTK_CALL MGTK::HideCursor
|
|
|
|
;; Restore menu
|
|
MGTK_CALL MGTK::DrawMenu
|
|
sta RAMWRTOFF
|
|
sta RAMRDOFF
|
|
yax_call JUMP_TABLE_MGTK_RELAY, MGTK::HiliteMenu, last_menu_click_params
|
|
sta RAMWRTON
|
|
sta RAMRDON
|
|
|
|
;; Force desktop redraw
|
|
MGTK_CALL MGTK::CloseWindow, winfo
|
|
DESKTOP_CALL DT_REDRAW_ICONS
|
|
|
|
MGTK_CALL MGTK::ShowCursor
|
|
rts ; exits input loop
|
|
.endproc
|
|
|
|
.proc show_file
|
|
jsr get_file_eof
|
|
|
|
;; If bigger than $2000, assume DHR
|
|
|
|
lda get_eof_params::eof ; fancy 3-byte unsigned compare
|
|
cmp #<(hires_size+1)
|
|
lda get_eof_params::eof+1
|
|
sbc #>(hires_size+1)
|
|
lda get_eof_params::eof+2
|
|
sbc #^(hires_size+1)
|
|
bcc :+
|
|
jmp show_dhr_file
|
|
|
|
;; If bigger than 576, assume HR
|
|
|
|
: lda get_eof_params::eof
|
|
cmp #<(minipix_src_size+1)
|
|
lda get_eof_params::eof+1
|
|
sbc #>(minipix_src_size+1)
|
|
bcc :+
|
|
jmp show_hr_file
|
|
|
|
;; Otherwise, assume Minipix
|
|
|
|
: jmp show_minipix_file
|
|
.endproc
|
|
|
|
.proc show_hr_file
|
|
sta PAGE2OFF
|
|
jsr read_file
|
|
jsr close_file
|
|
|
|
jsr hr_to_dhr
|
|
rts
|
|
.endproc
|
|
|
|
.proc show_dhr_file
|
|
ptr := $06
|
|
|
|
;; AUX memory half
|
|
sta PAGE2OFF
|
|
jsr read_file
|
|
|
|
;; NOTE: Why not just load into Aux directly by setting
|
|
;; PAGE2ON? This works unless loading from a RamWorks-based
|
|
;; RAM Disk, where things get messed up. This is slightly
|
|
;; slower in the non-RamWorks case.
|
|
;; TODO: Load directly into Aux if RamWorks is not present.
|
|
|
|
;; Copy MAIN to AUX
|
|
|
|
sta CLR80COL ; read main, write aux
|
|
sta RAMRDOFF
|
|
sta RAMWRTON
|
|
|
|
copy16 #hires, ptr
|
|
ldx #>hires_size ; number of pages to copy
|
|
ldy #0
|
|
: lda (ptr),y
|
|
sta (ptr),y
|
|
iny
|
|
bne :-
|
|
inc ptr+1
|
|
dex
|
|
bne :-
|
|
|
|
sta RAMWRTON ; read aux, write aux
|
|
sta RAMRDON
|
|
sta SET80COL
|
|
|
|
;; MAIN memory half
|
|
sta PAGE2OFF
|
|
jsr read_file
|
|
jsr close_file
|
|
|
|
rts
|
|
.endproc
|
|
|
|
|
|
.proc show_minipix_file
|
|
jsr set_bw_mode
|
|
|
|
;; Load file at minipix_src_buf (MAIN $1800)
|
|
jsr read_minipix_file
|
|
jsr close_file
|
|
|
|
;; Convert (in main)
|
|
sta RAMWRTOFF
|
|
sta RAMRDOFF
|
|
jsr convert_minipix_to_bitmap
|
|
sta RAMWRTON
|
|
sta RAMRDON
|
|
|
|
;; Copy main>aux
|
|
copy16 #minipix_dst_buf, STARTLO
|
|
copy16 #minipix_dst_buf, DESTINATIONLO
|
|
copy16 #(minipix_dst_buf+minipix_dst_size), ENDLO
|
|
sec ; main>aux
|
|
jsr AUXMOVE
|
|
|
|
;; Draw
|
|
MGTK_CALL MGTK::PaintBits, paintbits_params
|
|
|
|
rts
|
|
|
|
minipix_width = 88 * 2
|
|
minipix_height = 52
|
|
|
|
.proc paintbits_params
|
|
viewloc: DEFINE_POINT (screen_width - minipix_width)/2, (screen_height - minipix_height)/2
|
|
mapbits: .addr minipix_dst_buf
|
|
mapwidth: .byte 26
|
|
reserved: .byte 0
|
|
maprect: DEFINE_RECT 0,0,minipix_width-1,minipix_height-1
|
|
.endproc
|
|
|
|
.endproc
|
|
|
|
|
|
|
|
;;; ============================================================
|
|
;;; Convert single hires to double hires
|
|
|
|
;;; Assumes the image is loaded to MAIN $2000 and
|
|
;;; relies on the hr_to_dhr.inc table.
|
|
|
|
.proc hr_to_dhr
|
|
ptr := $06
|
|
rows = 192
|
|
cols = 40
|
|
spill := $08 ; spill-over
|
|
|
|
lda #0 ; row
|
|
rloop: pha
|
|
tax
|
|
copy hires_table_lo,x, ptr
|
|
copy hires_table_hi,x, ptr+1
|
|
|
|
ldy #cols-1 ; col
|
|
|
|
copy #0, spill ; spill-over
|
|
|
|
cloop: lda (ptr),y
|
|
tax
|
|
|
|
bmi hibitset
|
|
|
|
;; complex case - need to spill in bit from prev col and store
|
|
|
|
lda hr_to_dhr_aux,x
|
|
sta PAGE2ON
|
|
sta (ptr),y
|
|
lda hr_to_dhr_main,x
|
|
ora spill ; apply previous spill bit (to bit 6)
|
|
sta PAGE2OFF
|
|
sta (ptr),y
|
|
|
|
ror ; move high bit to bit 6
|
|
and #(1 << 6)
|
|
sta spill
|
|
|
|
jmp next
|
|
|
|
hibitset:
|
|
;; simple case - no bit spillage
|
|
lda hr_to_dhr_aux,x
|
|
sta PAGE2ON
|
|
sta (ptr),y
|
|
lda hr_to_dhr_main,x
|
|
sta PAGE2OFF
|
|
sta (ptr),y
|
|
|
|
copy #0, spill ; no spill bit
|
|
next:
|
|
dey
|
|
bpl cloop
|
|
|
|
pla
|
|
inc
|
|
cmp #rows
|
|
bne rloop
|
|
|
|
;; TODO: Restore PAGE2 state?
|
|
done: sta PAGE2OFF
|
|
rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Minipix images
|
|
|
|
.proc convert_minipix_to_bitmap
|
|
rows = 52
|
|
cols = 88 ; pixels
|
|
|
|
src := $06
|
|
dst := $08
|
|
|
|
copy16 #minipix_src_buf, src
|
|
copy16 #minipix_dst_buf, dst
|
|
|
|
;; c/o Kent Dickey on comp.sys.apple2.programmer
|
|
;; https://groups.google.com/d/msg/comp.sys.apple2.programmer/XB0jUEvrAhE/loRorS5fBwAJ
|
|
|
|
ldx #rows
|
|
stx row
|
|
ldy #0 ; Y remains unchanged throughout
|
|
|
|
;; For each row...
|
|
dorow: ldx #8
|
|
stx srcbit
|
|
ldx #7
|
|
stx dstbit
|
|
ldx #cols
|
|
|
|
;; Process each bit
|
|
: jsr getbit
|
|
jsr putbit2
|
|
dex
|
|
bne :-
|
|
|
|
;; We've written out 88*2 bits = 176 bits. This means 1 bit was shifted into
|
|
;; the last bit. We need to get it from the MSB to the LSB, so it needs
|
|
;; to be shifted down 7 bits
|
|
: clc
|
|
jsr putbit1
|
|
dex
|
|
cpx #AS_BYTE(-7) ; do 7 times == 7 bits
|
|
bne :-
|
|
|
|
dec row
|
|
bne dorow
|
|
rts
|
|
|
|
.proc getbit
|
|
lda (src),y
|
|
rol
|
|
sta (src),y
|
|
dec srcbit
|
|
bne done
|
|
|
|
inc src
|
|
bne :+
|
|
inc src+1
|
|
: lda #8
|
|
sta srcbit
|
|
|
|
done: rts
|
|
.endproc
|
|
|
|
.proc putbit2
|
|
php
|
|
jsr putbit1
|
|
plp
|
|
;; fall through
|
|
.endproc
|
|
.proc putbit1
|
|
lda (dst),y
|
|
ror
|
|
sta (dst),y
|
|
dec dstbit
|
|
bne done
|
|
|
|
ror ; shift once more to get bits in right place
|
|
sta (dst),y
|
|
inc dst
|
|
bne :+
|
|
inc dst+1
|
|
: lda #7
|
|
sta dstbit
|
|
|
|
done: rts
|
|
.endproc
|
|
|
|
srcbit: .byte 0
|
|
dstbit: .byte 0
|
|
row: .byte 0
|
|
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Color/B&W Toggle
|
|
|
|
mode: .byte 0 ; 0 = B&W, $80 = color
|
|
|
|
.proc toggle_mode
|
|
lda mode
|
|
bne set_bw_mode
|
|
;; fall through
|
|
.endproc
|
|
|
|
.proc set_color_mode
|
|
lda mode
|
|
bne done
|
|
copy #$80, mode
|
|
|
|
copy16 #JUMP_TABLE_COLOR_MODE, call_main_addr
|
|
jsr call_main_trampoline
|
|
|
|
done: rts
|
|
.endproc
|
|
|
|
.proc set_bw_mode
|
|
lda mode
|
|
beq done
|
|
copy #0, mode
|
|
|
|
copy16 #JUMP_TABLE_MONO_MODE, call_main_addr
|
|
jsr call_main_trampoline
|
|
|
|
done: rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.include "inc/hires_table.inc"
|
|
.include "inc/hr_to_dhr.inc"
|
|
|
|
;;; ============================================================
|
|
|
|
da_end:
|