From d8baeddbe01069592fb96d2b3aea8b0e0b40a8d2 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Sun, 9 Dec 2018 20:08:57 -0800 Subject: [PATCH] Restore new DAs to fixes branch This reverts commit 6788d153af2bac069ff3508cecca972be0989926. --- desk.acc/README.md | 15 +- desk.acc/TARGETS | 5 + desk.acc/eyes.s | 685 +++++++++++++++++++ desk.acc/res/README_DAS.txt | 27 + desk.acc/run.basic.here.s | 178 +++++ desk.acc/screen.dump.s | 234 +++++++ desk.acc/show.image.file.s | 718 +++++++++++++++++++ desk.acc/this.apple.s | 1291 +++++++++++++++++++++++++++++++++++ 8 files changed, 3151 insertions(+), 2 deletions(-) create mode 100644 desk.acc/eyes.s create mode 100644 desk.acc/run.basic.here.s create mode 100644 desk.acc/screen.dump.s create mode 100644 desk.acc/show.image.file.s create mode 100644 desk.acc/this.apple.s diff --git a/desk.acc/README.md b/desk.acc/README.md index fd02c76..8c21383 100644 --- a/desk.acc/README.md +++ b/desk.acc/README.md @@ -6,6 +6,17 @@ Disassembly of the original desk accessories: * [Show Text File](show.text.file.s) - in progress! 95% complete * [Sort Directory](sort.directory.s) - in progress! 60% complete +New desk accessories: + +* [Show Image File](show.image.file.s) + * Select an image file (8k Hires or 16k Double Hires), then choose this DA to preview it. +* [This Apple](this.apple.s) + * Gives details about the computer, expanded memory, and what's in each slot. +* [Eyes](eyes.s) + * Eyes that follow the mouse. +* [Screen Dump](screen.dump.s) + * Dumps a screenshot to an ImageWriter II attached to a Super Serial Card in Slot 1. + See [API.md](API.md) for programming details ## Files @@ -17,10 +28,10 @@ See [API.md](API.md) for programming details ## Build Instructions On Unix-like systems (including Mac OS X) `make all` should build -the desk accessory files into `out/` +the desk accessory files (original and new) into `out/` output with a `.built` suffix. -The `.built` and `.bin` files can be compared +For the original DAs, the `.built` and `.bin` files can be compared using `diff` to ensure that no changes have been introduced by the disassembly process. diff --git a/desk.acc/TARGETS b/desk.acc/TARGETS index c731679..25b9f57 100644 --- a/desk.acc/TARGETS +++ b/desk.acc/TARGETS @@ -3,3 +3,8 @@ show.text.file date puzzle sort.directory +show.image.file +this.apple +eyes +screen.dump +run.basic.here diff --git a/desk.acc/eyes.s b/desk.acc/eyes.s new file mode 100644 index 0000000..d48bf99 --- /dev/null +++ b/desk.acc/eyes.s @@ -0,0 +1,685 @@ + .setcpu "6502" + + .include "apple2.inc" + .include "../inc/apple2.inc" + .include "../mgtk.inc" + .include "../desktop.inc" + .include "../macros.inc" + .include "../inc/fp_macros.inc" + +;;; ============================================================ + + .org $800 + +entry: + +;;; Copy the DA to AUX for easy bank switching +.scope + lda ROMIN2 + copy16 #$0800, STARTLO + copy16 #da_end, ENDLO + copy16 #$0800, DESTINATIONLO + sec ; main>aux + jsr AUXMOVE + lda LCBANK1 + lda LCBANK1 +.endscope + +.scope + ;; run the DA + sta RAMRDON + sta RAMWRTON + jsr init + + ;; tear down/exit + sta ALTZPON + lda LCBANK1 + lda LCBANK1 + + ;; back to main for exit + sta RAMRDOFF + sta RAMWRTOFF + rts +.endscope + +;;; ============================================================ + +da_window_id := 60 +da_width := screen_width / 3 +da_height := screen_height / 3 +da_left := (screen_width - da_width)/2 +da_top := 50 + +str_title: + PASCAL_STRING "Eyes" + +;;; TODO: Allow resizing + +.proc winfo +window_id: .byte da_window_id +options: .byte MGTK::Option::go_away_box +title: .addr str_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 / 5 +mincontlength: .word screen_height / 5 +maxcontwidth: .word screen_width +maxcontlength: .word screen_height +port: +viewloc: DEFINE_POINT da_left, da_top +mapbits: .addr MGTK::screen_mapbits +mapwidth: .word MGTK::screen_mapwidth +maprect: DEFINE_RECT 0, 0, da_width, da_height, maprect +pattern: .res 8, $FF +colormasks: .byte MGTK::colormask_and, MGTK::colormask_or +penloc: DEFINE_POINT 0, 0 +penwidth: .byte 1 +penheight: .byte 1 +penmode: .byte 0 +textback: .byte $7F +textfont: .addr DEFAULT_FONT +nextwinfo: .addr 0 +.endproc + +;;; ============================================================ + + +.proc event_params +kind: .byte 0 +;;; EventKind::key_down +key := * +modifiers := * + 1 +;;; EventKind::update +window_id := * +;;; otherwise +xcoord := * +ycoord := * + 2 + .res 4 +.endproc + +.proc findwindow_params +mousex: .word 0 +mousey: .word 0 +which_area: .byte 0 +window_id: .byte 0 +.endproc + +.proc trackgoaway_params +clicked: .byte 0 +.endproc + +.proc dragwindow_params +window_id: .byte 0 +dragx: .word 0 +dragy: .word 0 +moved: .byte 0 +.endproc + +.proc winport_params +window_id: .byte da_window_id +port: .addr grafport +.endproc + + +.proc preserve_zp_params +flag: .byte MGTK::zp_preserve +.endproc + +.proc overwrite_zp_params +flag: .byte MGTK::zp_overwrite +.endproc + +.proc screentowindow_params +window_id: .byte da_window_id + DEFINE_POINT 0, 0, screen + DEFINE_POINT 0, 0, window +.endproc + mx := screentowindow_params::window::xcoord + my := screentowindow_params::window::ycoord + +.proc grafport +viewloc: DEFINE_POINT 0, 0 +mapbits: .word 0 +mapwidth: .word 0 +cliprect: DEFINE_RECT 0, 0, 0, 0 +pattern: .res 8, 0 +colormasks: .byte 0, 0 +penloc: DEFINE_POINT 0, 0 +penwidth: .byte 0 +penheight: .byte 0 +penmode: .byte 0 +textback: .byte 0 +textfont: .addr 0 +.endproc + +grow_box_width := 17 +grow_box_height := 7 + +.proc grow_box_params +viewloc: DEFINE_POINT 0, 0, viewloc +mapbits: .addr grow_box_bitmap +mapwidth: .byte 3 +reserved: .byte 0 +cliprect: DEFINE_RECT 2, 2, 19, 9 +.endproc + +grow_box_bitmap: + .byte px(%1111111),px(%1111111),px(%1111111) + .byte px(%1000000),px(%0000000),px(%0000001) + .byte px(%1001111),px(%1111110),px(%0000001) + .byte px(%1001100),px(%0000111),px(%1111001) + .byte px(%1001100),px(%0000110),px(%0011001) + .byte px(%1001100),px(%0000110),px(%0011001) + .byte px(%1001111),px(%1111110),px(%0011001) + .byte px(%1000011),px(%0000000),px(%0011001) + .byte px(%1000011),px(%1111111),px(%1111001) + .byte px(%1000000),px(%0000000),px(%0000001) + .byte px(%1111111),px(%1111111),px(%1111111) + +;;; ============================================================ + +.proc init + sta ALTZPON + lda LCBANK1 + lda LCBANK1 + + ;; Don't let MGTK smash zero page + MGTK_CALL MGTK::SetZP1, preserve_zp_params + lda #0 + sta SHIFT_SIGN_EXT ; Must zero before using FP ops + + MGTK_CALL MGTK::OpenWindow, winfo + jsr draw_window + MGTK_CALL MGTK::FlushEvents + ;; fall through +.endproc + +.proc input_loop + MGTK_CALL MGTK::GetEvent, event_params + bne exit + lda event_params::kind + cmp #MGTK::EventKind::button_down + beq handle_down + cmp #MGTK::EventKind::key_down + beq handle_key + cmp #MGTK::EventKind::no_event + beq handle_no_event + jmp input_loop +.endproc + +.proc exit + MGTK_CALL MGTK::CloseWindow, winfo + DESKTOP_CALL DT_REDRAW_ICONS + MGTK_CALL MGTK::SetZP1, overwrite_zp_params + rts +.endproc + +;;; ============================================================ + +.proc handle_key + lda event_params::key + cmp #CHAR_ESCAPE + beq exit + bne input_loop +.endproc + +;;; ============================================================ + +.proc handle_down + copy16 event_params::xcoord, findwindow_params::mousex + copy16 event_params::ycoord, findwindow_params::mousey + MGTK_CALL MGTK::FindWindow, findwindow_params + bne exit + lda findwindow_params::window_id + cmp winfo::window_id + bne input_loop + lda findwindow_params::which_area + cmp #MGTK::Area::close_box + beq handle_close + cmp #MGTK::Area::dragbar + beq handle_drag + cmp #MGTK::Area::content + bne :+ + jmp handle_grow +: jmp input_loop +.endproc + +;;; ============================================================ + +.proc handle_close + MGTK_CALL MGTK::TrackGoAway, trackgoaway_params + lda trackgoaway_params::clicked + beq input_loop + bne exit +.endproc + +;;; ============================================================ + +.proc handle_no_event + ;; First time? Need to store last coords + lda has_last_coords + bne test + inc has_last_coords + bne moved + + ;; Moved? +test: + lda event_params::xcoord + cmp screentowindow_params::screen::xcoord + bne moved + lda event_params::xcoord+1 + cmp screentowindow_params::screen::xcoord+1 + bne moved + lda event_params::ycoord + cmp screentowindow_params::screen::ycoord + bne moved + lda event_params::ycoord+1 + cmp screentowindow_params::screen::ycoord+1 + beq done + +moved: copy16 event_params::xcoord, screentowindow_params::screen::xcoord + copy16 event_params::ycoord, screentowindow_params::screen::ycoord + MGTK_CALL MGTK::ScreenToWindow, screentowindow_params + jsr draw_window + +done: jmp input_loop + +.endproc + +;;; ============================================================ + +.proc handle_drag + copy winfo::window_id, dragwindow_params::window_id + copy16 event_params::xcoord, dragwindow_params::dragx + copy16 event_params::ycoord, dragwindow_params::dragy + MGTK_CALL MGTK::DragWindow, dragwindow_params +common: lda dragwindow_params::moved + bpl :+ + + ;; Draw DeskTop's windows + sta RAMRDOFF + sta RAMWRTOFF + jsr JUMP_TABLE_REDRAW_ALL + sta RAMRDON + sta RAMWRTON + + ;; Draw DA's window + lda #0 + sta has_last_coords + sta has_drawn_outline + jsr draw_window + + ;; Draw DeskTop icons + DESKTOP_CALL DT_REDRAW_ICONS + +: jmp input_loop + +.endproc + +;;; ============================================================ + +.proc handle_grow + ;; Is the hit within the grow box area? + copy16 event_params::xcoord, screentowindow_params::screen::xcoord + copy16 event_params::ycoord, screentowindow_params::screen::ycoord + MGTK_CALL MGTK::ScreenToWindow, screentowindow_params + sub16 winfo::maprect::x2, mx, tmpw + cmp16 #grow_box_width, tmpw + bcc nope + sub16 winfo::maprect::y2, my, tmpw + cmp16 #grow_box_height, tmpw + bcc nope + + ;; Initiate the grow... re-using the drag logic + copy winfo::window_id, dragwindow_params::window_id + copy16 event_params::xcoord, dragwindow_params::dragx + copy16 event_params::ycoord, dragwindow_params::dragy + MGTK_CALL MGTK::GrowWindow, dragwindow_params + jmp handle_drag::common + +nope: jmp input_loop + +tmpw: .word 0 +.endproc + +;;; ============================================================ + +penxor: .byte MGTK::penXOR +notpencopy: .byte MGTK::notpencopy + +penw := 8 +penh := 4 +pupilw := penw * 2 +pupilh := penh * 2 + +.proc outline_pensize +penwidth: .byte penw +penheight: .byte penh +.endproc + +.proc pupil_pensize +penwidth: .byte pupilw +penheight: .byte pupilh +.endproc + +;;; Flag set once we have coords from a move event +has_last_coords: + .byte 0 + +;;; Flag set once outline is drawn (cleared on window move) +has_drawn_outline: + .byte 0 + +;;; Saved coords +pos_l: DEFINE_POINT 0, 0, pos_l +pos_r: DEFINE_POINT 0, 0, pos_r + +;;; ============================================================ + +.proc draw_window + ;; Defer if content area is not visible + MGTK_CALL MGTK::GetWinPort, winport_params + cmp #MGTK::Error::window_obscured + bne :+ + rts +: + ;; Defer until we have mouse coords + lda has_last_coords + bne :+ + rts +: + + MGTK_CALL MGTK::SetPort, grafport + MGTK_CALL MGTK::HideCursor + + copy16 winfo::maprect::x2, rx ; width / 4 + lsr16 rx + lsr16 rx + copy16 winfo::maprect::y2, ry ; height / 2 + lsr16 ry + + lda has_drawn_outline + beq :+ + jmp erase_pupils +: inc has_drawn_outline + + ;; Draw resize box + MGTK_CALL MGTK::SetPenMode, notpencopy + sub16 winfo::maprect::x2, #grow_box_width, grow_box_params::viewloc::xcoord + sub16 winfo::maprect::y2, #grow_box_height, grow_box_params::viewloc::ycoord + MGTK_CALL MGTK::PaintBits, grow_box_params + + ;; Draw outline + MGTK_CALL MGTK::SetPenMode, notpencopy + MGTK_CALL MGTK::SetPenSize, outline_pensize + + copy16 rx, cx + copy16 ry, cy + jsr draw_outline + + add16 rx, cx, cx + add16 rx, cx, cx + jsr draw_outline + + ;; Skip erasing pupils if we're redrawing + jmp draw_pupils + +erase_pupils: + MGTK_CALL MGTK::SetPenMode, penxor + MGTK_CALL MGTK::SetPenSize, pupil_pensize + + MGTK_CALL MGTK::MoveTo, pos_l + MGTK_CALL MGTK::LineTo, pos_l + MGTK_CALL MGTK::MoveTo, pos_r + MGTK_CALL MGTK::LineTo, pos_r + +draw_pupils: + MGTK_CALL MGTK::SetPenMode, penxor + MGTK_CALL MGTK::SetPenSize, pupil_pensize + + copy16 rx, cx + copy16 ry, cy + jsr compute_pupil_pos + sub16 ppx, #pupilw/2, pos_l::xcoord + sub16 ppy, #pupilh/2, pos_l::ycoord + MGTK_CALL MGTK::MoveTo, pos_l + MGTK_CALL MGTK::LineTo, pos_l + + add16 rx, cx, cx + add16 rx, cx, cx + jsr compute_pupil_pos + sub16 ppx, #pupilw/2, pos_r::xcoord + sub16 ppy, #pupilh/2, pos_r::ycoord + MGTK_CALL MGTK::MoveTo, pos_r + MGTK_CALL MGTK::LineTo, pos_r + + MGTK_CALL MGTK::ShowCursor +done: rts + +tmpw: .word 0 +.endproc + +;;; ============================================================ +;;; Common input params + +rx: .word 0 +ry: .word 0 + +cx: .word 0 +cy: .word 0 + +;;; ============================================================ +;;; Compute pupil location +;;; +;;; Inputs: mx, my, cx, cy, rx, ry +;;; Outputs: ppx, ppy + +ppx: .word 0 +ppy: .word 0 + +.proc compute_pupil_pos + lda ROMIN2 + + fac_load_int cx + fac_store cxf + + fac_load_int cy + fac_store cyf + + ;; pupil shouldn't overlap border + sub16 rx, #penw, tmpw + sub16 tmpw, #pupilw, tmpw + fac_load_int tmpw + fac_store prx + + sub16 ry, #penh, tmpw + sub16 tmpw, #pupilh, tmpw + fac_load_int tmpw + fac_store pry + + ;; x scale, so math is circular + ;; xs = pry / prx + + fac_load prx + fac_div pry + fac_store scale + + ;; mouse delta, in transformed space + ;; dx = (mx - cx) * xs + ;; dy = mx - cy + + fac_load_int mx ; dx = (mx - cx) * xs + fac_store tmpf + fac_load cxf + fac_sub tmpf + fac_mul scale + fac_store dx + + fac_load_int my ; dy = mx - cy + fac_store tmpf + fac_load cyf + fac_sub tmpf + fac_store dy + + ;; d = SQR(dx * dx + dy * dy) + + fac_load dx + fac_mul dx + fac_store tmpf + fac_load dy + fac_mul dy + fac_add tmpf + + jsr SQR ; ??? Crashes here after window drag + + ;; if d > pry: + ;; f = pry / d + ;; dx = f * dx + ;; dy = f * dy + + fac_comp pry + bmi skip + + fac_div pry ; f = pry / d + fac_store tmpf + + fac_mul dx ; dx = f * dx + fac_store dx + + fac_load tmpf ; dy = f * dy + fac_mul dy + fac_store dy +skip: + + ;; plot coords + ;; ppx = (dx / xs) + cx + ;; ppy = dy + cy + + fac_load scale ; ppx = (dx / xs) + cx + fac_div dx + fac_add cxf + fac_store_int ppx + + fac_load dy ; ppy = dy + cy + fac_add cyf + fac_store_int ppy + + lda LCBANK1 + lda LCBANK1 + + rts + +tmpw: .word 0 +tmpf: DEFINE_FLOAT + +scale: DEFINE_FLOAT +dx: DEFINE_FLOAT +dy: DEFINE_FLOAT +pry: DEFINE_FLOAT +prx: DEFINE_FLOAT +cxf: DEFINE_FLOAT +cyf: DEFINE_FLOAT +.endproc + +;;; ============================================================ +;;; Draw eye outlines as a 36-sided polygon +;;; Inputs: cx, cy, rx, ry + +.proc draw_outline + segments := 36 + + lda ROMIN2 + + fac_load_int segw + fac_div CON_TWO_PI + fac_store step + + sub16 cx, #penw/2, tmpw + fac_load_int tmpw + fac_store cxf + + sub16 cy, #penh/2, tmpw + fac_load_int tmpw + fac_store cyf + + sub16 rx, #penw/2, tmpw + fac_load_int tmpw + fac_store rxf + + sub16 ry, #penh/2, tmpw + fac_load_int tmpw + fac_store ryf + + lda #segments + sta count + + jsr ZERO_FAC + fac_store theta + + fac_load rxf + fac_add cxf + fac_store_int ptx + + fac_load cyf + fac_store_int pty + + lda LCBANK1 + lda LCBANK1 + + MGTK_CALL MGTK::MoveTo, drawpos + +loop: + lda ROMIN2 + + fac_load theta + fac_add step + fac_store theta + + jsr COS + fac_mul rxf + fac_add cxf + fac_store_int ptx + + fac_load theta + jsr SIN + fac_mul ryf + fac_add cyf + fac_store_int pty + + lda LCBANK1 + lda LCBANK1 + + MGTK_CALL MGTK::LineTo, drawpos + + dec count + bpl loop + rts + +count: .byte 0 +segw: .word segments +tmpw: .word 0 +step: DEFINE_FLOAT +theta: DEFINE_FLOAT +rxf: DEFINE_FLOAT +ryf: DEFINE_FLOAT +cxf: DEFINE_FLOAT +cyf: DEFINE_FLOAT + +drawpos: DEFINE_POINT 0, 0, drawpos + ptx := drawpos::xcoord + pty := drawpos::ycoord +.endproc + + +;;; ============================================================ + +da_end = * +.assert * < $1B00, error, "DA too big" + ;; I/O Buffer starts at MAIN $1C00 + ;; ... but icon tables start at AUX $1B00 diff --git a/desk.acc/res/README_DAS.txt b/desk.acc/res/README_DAS.txt index f083ab4..5a7a1cb 100644 --- a/desk.acc/res/README_DAS.txt +++ b/desk.acc/res/README_DAS.txt @@ -22,3 +22,30 @@ the menu order: * Restart Source code can be found at: https://github.com/inexorabletash/a2d + + +Show Image File +--------------- +In Apple II Desktop, select an image file. Unfortunately, these are +hard to identify in A2D; they appear as a binary file (icon is <01>) +and are usually either 17 (single hi-res) or 33 (double hi-res) blocks +- you can check View > By Name or use Special > Get Info... to see the +size. + +Then select Show Image File from the Apple menu. The image should +appear. If garbage appears, it was probably not an image file. You can +move the mouse pointer while the image is displayed. Click the mouse +button or press Escape to return to the DeskTop. + + +This Apple +---------- +Select this item from the Apple menu to see an overview of the model +of computer, the CPU, an estimate of RamWorks memory expansion (if +present), and what cards can be identified in each slot. + + +Eyes +---- +Select this for a demo showing two eyes that follow the mouse cursor. +The window can be moved and resized. diff --git a/desk.acc/run.basic.here.s b/desk.acc/run.basic.here.s new file mode 100644 index 0000000..0645b6e --- /dev/null +++ b/desk.acc/run.basic.here.s @@ -0,0 +1,178 @@ +;;; ============================================================ +;;; RUN.BASIC.HERE - Desk Accessory +;;; +;;; Launches BASIC.SYSTEM with PREFIX set to the path of the +;;; current window. BYE will return to DeskTop. Looks for +;;; BASIC.SYSTEM up the directory tree from DeskTop itself. +;;; ============================================================ + + .setcpu "6502" + + .include "apple2.inc" + .include "../inc/apple2.inc" + .include "../inc/prodos.inc" + .include "../mgtk.inc" + .include "../desktop.inc" + .include "../macros.inc" + +;;; ============================================================ + + .org $800 + +;;; ============================================================ + + jmp start + +;;; ============================================================ + +bs_path: .res 65, 0 +prefix_path: .res 65, 0 + + DEFINE_GET_FILE_INFO_PARAMS get_file_info_params, bs_path + DEFINE_OPEN_PARAMS open_params, bs_path, $C00 + DEFINE_READ_PARAMS read_params, $2000, $BF00-$2000 + DEFINE_CLOSE_PARAMS close_params + DEFINE_SET_PREFIX_PARAMS set_prefix_params, prefix_path + DEFINE_QUIT_PARAMS quit_params + +;;; ============================================================ + +start: + ;; Get active window's path + jsr get_win_path + beq :+ + lda #$FA ; "This file cannot be run" - not perfect + bne fail + + ;; Find BASIC.SYSTEM +: jsr check_basic_system + beq :+ + lda #$FE ; "BASIC.SYSTEM not found" + bne fail + + ;; Restore to normal state +: sta ALTZPOFF + lda ROMIN2 + jsr SETVID + jsr SETKBD + jsr INIT + jsr HOME + sta TXTSET + sta LOWSCR + sta LORES + sta MIXCLR + sta DHIRESOFF + sta CLRALTCHAR + sta CLR80VID + sta CLR80COL + + ;; TODO: restore /RAM? + + ;; Set PREFIX + MLI_CALL SET_PREFIX, set_prefix_params + bcs quit + + ;; Load BS + MLI_CALL OPEN, open_params + bcs quit + lda open_params::ref_num + sta read_params::ref_num + sta close_params::ref_num + + MLI_CALL READ, read_params + bcs quit + + MLI_CALL CLOSE, close_params + bcs quit + + ;; Launch + jmp $2000 + + + ;; Early errors - show alert and return to DeskTop +fail: jsr JUMP_TABLE_ALERT_X + rts + + ;; Late errors - QUIT, which should relaunch DeskTop +quit: MLI_CALL QUIT, quit_params + + +;;; ============================================================ + + DEFINE_GET_PREFIX_PARAMS get_prefix_params, bs_path + +.proc check_basic_system + axy_call JUMP_TABLE_MLI, GET_PREFIX, get_prefix_params + bne no_bs + + lda bs_path + sta path_length + + ;; Append BASIC.SYSTEM to path and check for file. +loop: ldx path_length + ldy #0 +: inx + iny + copy str_basic_system,y, bs_path,x + cpy str_basic_system + bne :- + stx bs_path + + axy_call JUMP_TABLE_MLI, GET_FILE_INFO, get_file_info_params + bne not_found + rts + + ;; Pop off a path segment and try again. +not_found: + ldx path_length + dex +: lda bs_path,x + cmp #'/' + beq found_slash + dex + bne :- + +found_slash: + cpx #1 + beq no_bs + stx path_length + jmp loop + +no_bs: return #1 + + ;; length of directory path e.g. "/VOL/DIR/" +path_length: + .byte 0 + +str_basic_system: + PASCAL_STRING "BASIC.SYSTEM" +.endproc + +;;; ============================================================ + +.proc get_win_path + ptr := $06 + + yax_call JUMP_TABLE_MGTK_RELAY, MGTK::FrontWindow, ptr + lda ptr ; any window open? + beq fail + cmp #9 ; windows are 1-8 + bcs fail + + asl a ; window index * 2 + tay + copy16 path_table,y, ptr + + ldy #0 + lda (ptr),y + tay +: copy (ptr),y, prefix_path,y + dey + bpl :- + return #0 + +fail: return #1 + +.endproc + +;;; ============================================================ diff --git a/desk.acc/screen.dump.s b/desk.acc/screen.dump.s new file mode 100644 index 0000000..0288c08 --- /dev/null +++ b/desk.acc/screen.dump.s @@ -0,0 +1,234 @@ + .setcpu "6502" + + .include "apple2.inc" + .include "../inc/apple2.inc" + .include "../inc/prodos.inc" + .include "../mgtk.inc" + .include "../desktop.inc" + .include "../macros.inc" + +;;; ============================================================ + + .org $800 + +;;; ============================================================ + + yax_call JUMP_TABLE_MGTK_RELAY, MGTK::HideCursor, 0 + yax_call JUMP_TABLE_MGTK_RELAY, MGTK::HiliteMenu, last_menu_click_params + jsr dump_screen + yax_call JUMP_TABLE_MGTK_RELAY, MGTK::HiliteMenu, last_menu_click_params + yax_call JUMP_TABLE_MGTK_RELAY, MGTK::ShowCursor, 0 + rts + +;;; ============================================================ + +.proc dump_screen + + SLOT1 := $C100 + + hbasl := $6 + screen_width := 560 + screen_height := 192 + + lda ROMIN2 + jsr print_screen + lda LCBANK1 + lda LCBANK1 + rts + +.proc send_spacing + ldy #0 +: lda spacing_sequence,y + beq done + jsr cout + iny + jmp :- +done: rts +.endproc + +.proc send_restore_state + ldy #$00 +: lda restore_state,y + beq done + jsr cout + iny + jmp :- +done: rts +.endproc + +.proc send_init_graphics + ldx #0 +: lda init_graphics,x + jsr cout + inx + cpx #6 + bne :- + rts +init_graphics: + .byte CHAR_ESCAPE,"G0560" ; Graphics, 560 data bytes +.endproc + +.proc send_row + ;; Tell printer to expect graphics + jsr send_init_graphics + ldy #0 + sty col_num + lda #1 + sta mask + lda #0 + sta x_coord + sta x_coord+1 + +col_loop: + lda #8 ; 8 vertical pixels per row + sta count + lda y_row + sta y_coord + + ;; Accumulate 8 pixels +y_loop: lda y_coord + jsr compute_hbasl ; Row address in screen + + lda col_num + lsr a ; Even or odd column? + tay + sta PAGE2OFF ; By default, read main mem $2000-$3FFF + bcs :+ ; But even columns come from aux, so... + sta PAGE2ON ; Read aux mem $2000-$3FFF + +: lda (hbasl),y ; Grab the whole byte + and mask ; Isolate the pixel we care about + cmp #1 ; Set carry if non-zero + ror accum ; And slide it into place + inc y_coord + dec count + bne y_loop + + ;; Send the 8 pixels to the printer. + lda accum ; Now output it + eor #$FF ; Invert pixels (screen vs. print) + sta PAGE2OFF ; Read main mem $2000-$3FFF + jsr cout ; And actually print + + ;; Done all pixels across? + lda x_coord + cmp #<(screen_width-1) + bne :+ + lda x_coord+1 + cmp #>(screen_width-1) + beq done + + ;; Next pixel to the right +: asl mask + bpl :+ ; Only 7 pixels per column + lda #1 + sta mask + inc col_num + +: inc x_coord + bne col_loop + inc x_coord+1 + bne col_loop + +done: sta PAGE2OFF ; Read main mem $2000-$3FFF + rts +.endproc + +.proc print_screen + ;; Init printer + jsr pr_num_1 + jsr send_spacing + + lda #0 + sta y_row + + ;; Print a row (560x8), CR+LF +loop: jsr send_row + lda #CHAR_RETURN + jsr cout + lda #CHAR_DOWN + jsr cout + + lda y_coord + sta y_row + cmp #screen_height + bcc loop + + ;; Finish up + lda #CHAR_RETURN + jsr cout + lda #CHAR_RETURN + jsr cout + jsr send_restore_state + + rts +.endproc + + ;; Given y-coordinate in A, compute HBASL-equivalent +.proc compute_hbasl + pha + and #$C7 + eor #$08 + sta $07 + and #$F0 + lsr a + lsr a + lsr a + sta hbasl + pla + and #$38 + asl a + asl a + eor hbasl + asl a + rol hbasl+1 + asl a + rol hbasl+1 + eor hbasl + sta hbasl + rts +.endproc + +.proc pr_num_1 + lda #>SLOT1 + sta COUT_HOOK+1 + lda #(hires_size+1) + lda get_eof_params::eof+2 + sbc #^(hires_size+1) + bcs dhr + + jsr show_hr_file + jmp close + +dhr: jsr show_dhr_file + +close: jsr close_file + rts +.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 + copy16 #hires, ptr + ldx #>hires_size ; number of pages to copy + ldy #0 +: sta PAGE2OFF ; from main + lda (ptr),y + sta PAGE2ON ; to aux + sta (ptr),y + iny + bne :- + inc ptr+1 + dex + bne :- + + ;; MAIN memory half + sta PAGE2OFF + jsr read_file + jsr close_file + + ;; TODO: Restore PAGE2 state? + + rts +.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 + lda hires_table_lo,x + sta ptr + lda hires_table_hi,x + sta ptr+1 + + ldy #cols-1 ; col + + lda #0 + sta 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 + + lda #0 ; no spill bit + sta spill +next: + dey + bpl cloop + + pla + inc + cmp #rows + bne rloop + + ;; TODO: Restore PAGE2 state? +done: sta PAGE2OFF + rts +.endproc + +;;; ============================================================ +;;; Stash/Unstash Menu Bar + +;;; Have not yet figured out how to force the menu to +;;; redraw, so instead we save the top 13 rows of the +;;; screen to a scratch buffer and restore after +;;; destroying the window. + + stash := $1200 ; Past DA code + rows = 13 + cols = 40 + +.proc stash_menu + src := $08 + dst := $06 + copy16 #stash, dst + + sta PAGE2ON + jsr inner + sta PAGE2OFF + +inner: + + lda #0 ; row # +rloop: pha + tax + lda hires_table_lo,x + sta src + lda hires_table_hi,x + sta src+1 + ldy #cols-1 +cloop: lda (src),y + sta (dst),y + dey + bpl cloop + + clc ; src += cols + lda src + adc #cols + sta src+1 + + clc ; dst += cols + lda dst + adc #cols + sta dst+1 + + pla + inc + cmp #rows + bcc rloop + rts +.endproc + +.proc unstash_menu + src := $08 + dst := $06 + copy16 #stash, src + + sta PAGE2ON + jsr inner + sta PAGE2OFF + +inner: + + lda #0 ; row # +rloop: pha + tax + lda hires_table_lo,x + sta dst + lda hires_table_hi,x + sta dst+1 + ldy #cols-1 +cloop: lda (src),y + sta (dst),y + dey + bpl cloop + + clc ; src += cols + lda src + adc #cols + sta src+1 + + clc ; dst += cols + lda dst + adc #cols + sta dst+1 + + pla + inc + cmp #rows + bcc rloop + rts +.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 + lda #$80 + sta mode + + ;; AppleColor Card - Mode 2 (Color 140x192) + sta SET80VID + lda AN3_OFF + lda AN3_ON + lda AN3_OFF + lda AN3_ON + lda AN3_OFF + + ;; IIgs? + jsr test_iigs + bcc iigs + + ;; Le Chat Mauve - COL140 mode + ;; (AN3 off, HR1 off, HR2 off, HR3 off) + ;; Skip on IIgs since emulators (KEGS/GSport/GSplus) crash. + sta HR2_OFF + sta HR3_OFF + bcs done + + ;; Apple IIgs - DHR Color +iigs: lda NEWVIDEO + and #<~(1<<5) ; Color + sta NEWVIDEO + +done: rts +.endproc + +.proc set_bw_mode + lda mode + beq done + lda #0 + sta mode + + ;; AppleColor Card - Mode 1 (Monochrome 560x192) + sta CLR80VID + lda AN3_OFF + lda AN3_ON + lda AN3_OFF + lda AN3_ON + sta SET80VID + lda AN3_OFF + + ;; IIgs? + jsr test_iigs + bcc iigs + + ;; Le Chat Mauve - BW560 mode + ;; (AN3 off, HR1 off, HR2 on, HR3 on) + ;; Skip on IIgs since emulators (KEGS/GSport/GSplus) crash. + sta HR2_ON + sta HR3_ON + bcs done + + ;; Apple IIgs - DHR B&W +iigs: lda NEWVIDEO + ora #(1<<5) ; B&W + sta NEWVIDEO + +done: rts +.endproc + +;;; Returns with carry clear if IIgs, set otherwise. +.proc test_iigs + lda ROMIN2 + sec + jsr ID_BYTE_FE1F + lda LCBANK1 + lda LCBANK1 + rts +.endproc + + .include "inc/hires_table.inc" + .include "inc/hr_to_dhr.inc" diff --git a/desk.acc/this.apple.s b/desk.acc/this.apple.s new file mode 100644 index 0000000..d3bcbf4 --- /dev/null +++ b/desk.acc/this.apple.s @@ -0,0 +1,1291 @@ + .setcpu "6502" + + .include "apple2.inc" + .include "../inc/apple2.inc" + .include "../inc/prodos.inc" + .include "../mgtk.inc" + .include "../desktop.inc" + .include "../macros.inc" + +;;; ============================================================ + + .org $800 + +entry: + +;;; Copy the DA to AUX for easy bank switching +.scope + lda ROMIN2 + copy16 #$0800, STARTLO + copy16 #da_end, ENDLO + copy16 #$0800, DESTINATIONLO + sec ; main>aux + jsr AUXMOVE + lda LCBANK1 + lda LCBANK1 +.endscope + +.scope + ;; run the DA + sta RAMRDON + sta RAMWRTON + jsr init + + ;; tear down/exit + sta ALTZPON + lda LCBANK1 + lda LCBANK1 + sta RAMRDOFF + sta RAMWRTOFF + rts +.endscope + +;;; ============================================================ + +da_window_id := 60 +da_width := 400 +da_height := 118 +da_left := (screen_width - da_width)/2 +da_top := 50 + +.proc winfo +window_id: .byte da_window_id +options: .byte MGTK::Option::go_away_box +title: .addr str_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 da_width +mincontlength: .word da_height +maxcontwidth: .word da_width +maxcontlength: .word da_height +port: +viewloc: DEFINE_POINT da_left, da_top +mapbits: .addr MGTK::screen_mapbits +mapwidth: .word MGTK::screen_mapwidth +maprect: DEFINE_RECT 0, 0, da_width, da_height +pattern: .res 8, $FF +colormasks: .byte MGTK::colormask_and, MGTK::colormask_or +penloc: DEFINE_POINT 0, 0 +penwidth: .byte 1 +penheight: .byte 1 +penmode: .byte 0 +textback: .byte $7F +textfont: .addr DEFAULT_FONT +nextwinfo: .addr 0 +.endproc + +str_title: + PASCAL_STRING "About this Apple II" + +;;; ============================================================ + +.proc iie_bitmap +viewloc: DEFINE_POINT 59, 5 +mapbits: .addr iie_bits +mapwidth: .byte 8 +reserved: .res 1 +maprect: DEFINE_RECT 0, 0, 50, 25 +.endproc + +.proc iic_bitmap +viewloc: DEFINE_POINT 62, 4 +mapbits: .addr iic_bits +mapwidth: .byte 7 +reserved: .res 1 +maprect: DEFINE_RECT 0, 0, 45, 27 +.endproc + +.proc iigs_bitmap +viewloc: DEFINE_POINT 65, 5 +mapbits: .addr iigs_bits +mapwidth: .byte 6 +reserved: .res 1 +maprect: DEFINE_RECT 0, 0, 38, 25 +.endproc + +.proc iii_bitmap +viewloc: DEFINE_POINT 57, 5 +mapbits: .addr iii_bits +mapwidth: .byte 8 +reserved: .res 1 +maprect: DEFINE_RECT 0, 0, 54, 24 +.endproc + +.proc iie_card_bitmap +viewloc: DEFINE_POINT 56, 9 +mapbits: .addr iie_card_bits +mapwidth: .byte 8 +reserved: .res 1 +maprect: DEFINE_RECT 0, 0, 55, 21 +.endproc + +.proc laser128_bitmap +viewloc: DEFINE_POINT 60, 4 +mapbits: .addr laser128_bits +mapwidth: .byte 7 +reserved: .res 1 +maprect: DEFINE_RECT 0, 0, 47, 29 +.endproc + + +iie_bits: + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110000),px(%0000000),px(%0000000),px(%0000000),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1001100),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011111),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0110000),px(%0000000),px(%0000000),px(%0000000),px(%0110011),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111),px(%1111111) + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0111100),px(%0000000),px(%0111111),px(%0000000),px(%0001111),px(%0011111),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111),px(%1111111) + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111),px(%1111111) + .byte px(%1111100),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0001111),px(%1111111) + .byte px(%1110001),px(%1110011),px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%1100011),px(%1111111) + .byte px(%1000111),px(%1001100),px(%1100110),px(%0110011),px(%0011001),px(%1001100),px(%1111000),px(%1111111) + .byte px(%0011110),px(%0110011),px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%0011110),px(%0111111) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1000111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111000),px(%1111111) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000011),px(%1111111) + + +iic_bits: + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000111),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1110011),px(%1111111) + .byte px(%1111110),px(%0111000),px(%0000000),px(%0000000),px(%0000000),px(%1110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1001100),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%1111111) + .byte px(%1111110),px(%0111000),px(%0000000),px(%0000000),px(%0000000),px(%1110011),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1110011),px(%1111111) + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000111),px(%1111111) + .byte px(%1111111),px(%1111100),px(%1111111),px(%1111111),px(%1111001),px(%1111111),px(%1111111) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111) + .byte px(%1100110),px(%1101101),px(%1011011),px(%0110110),px(%1101101),px(%1011011),px(%0011111) + .byte px(%1100110),px(%1101101),px(%1011011),px(%0110110),px(%1101101),px(%1011011),px(%0011111) + .byte px(%1001110),px(%1101101),px(%1011011),px(%0110110),px(%1101101),px(%1011011),px(%1001111) + .byte px(%1001110),px(%1101101),px(%1011011),px(%0110110),px(%1101101),px(%1011011),px(%1001111) + .byte px(%1001111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1001111) + .byte px(%0011110),px(%0110011),px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%1100111) + .byte px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%0011001),px(%1001100),px(%1100111) + .byte px(%0011110),px(%0110011),px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%1100111) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1100111) + .byte px(%1000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0001111) + +iigs_bits: + .byte px(%1000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0011111) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1001111) + .byte px(%0011000),px(%0000000),px(%0000000),px(%0000000),px(%0000001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1001100),px(%1100110),px(%0111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1001100),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1001111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011001),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1001111) + .byte px(%0011000),px(%0000000),px(%0000000),px(%0000000),px(%0000001),px(%1001111) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1001111) + .byte px(%1000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0011111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100110),px(%0110000),px(%0011111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111110),px(%0111111) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%1111111) + +iii_bits: + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000011),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110000),px(%0000000),px(%0000000),px(%0000000),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1001100),px(%1111110),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1111111),px(%1111110),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%0011111),px(%1111111),px(%1111110),px(%0110011),px(%0011001),px(%1111111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%0011001),px(%1111111) + .byte px(%1111110),px(%0110000),px(%0000000),px(%0000000),px(%0000000),px(%0111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1111111) + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000011),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111000),px(%0000000),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0111100),px(%0000111),px(%1111111),px(%1111111),px(%0000111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001),px(%1111111) + .byte px(%1111110),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000001),px(%1111111) + .byte px(%1111100),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111000),px(%1111111) + .byte px(%1110001),px(%1110011),px(%0011001),px(%1001100),px(%1100111),px(%1110011),px(%0011110),px(%0011111) + .byte px(%1000111),px(%1001100),px(%1100110),px(%0110011),px(%0011001),px(%1111100),px(%1100111),px(%1000111) + .byte px(%0011110),px(%0110011),px(%0011001),px(%1001100),px(%1100110),px(%0111111),px(%0011001),px(%1110011) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1110011) + .byte px(%1000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000111) + +iie_card_bits: + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000111),px(%1111111) + .byte px(%1100001),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1100111),px(%1111111) + .byte px(%1100001),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1100111),px(%1100111),px(%1111111) + .byte px(%1100001),px(%1111111),px(%1111111),px(%1111000),px(%0000011),px(%1100111),px(%1100111),px(%1111111) + .byte px(%1100001),px(%1000111),px(%1100110),px(%0111000),px(%0000011),px(%1111111),px(%1100111),px(%1000011) + .byte px(%1100001),px(%1000111),px(%1100110),px(%0111000),px(%0000011),px(%1111111),px(%1100111),px(%1000011) + .byte px(%1110011),px(%1111111),px(%1100110),px(%0111000),px(%0000011),px(%1111111),px(%1100111),px(%1000011) + .byte px(%1110011),px(%0000111),px(%1111111),px(%1111000),px(%0000011),px(%1100000),px(%1100110),px(%0000000) + .byte px(%1110011),px(%0000111),px(%1000011),px(%1111111),px(%1111111),px(%1100000),px(%1100111),px(%0000001) + .byte px(%1110011),px(%0000111),px(%1000011),px(%1111111),px(%1111111),px(%1100000),px(%1100111),px(%1000011) + .byte px(%1110011),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1100111),px(%1100111) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000111),px(%1111111) + .byte px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111) + .byte px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111100) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111100) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111100),px(%0000000),px(%0000000),px(%0011100) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111100) + .byte px(%0011111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111100) + .byte px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000) + .byte px(%1110011),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1100111) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000111) + +laser128_bits: + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111) + .byte px(%1111110),px(%0111000),px(%0000000),px(%0000000),px(%0000000),px(%1111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1001100),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%0011001),px(%1111111),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%0011111),px(%1111111),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0111111),px(%0011111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%0011111) + .byte px(%1111110),px(%0110011),px(%1111111),px(%1111111),px(%1111110),px(%0110011),px(%0011111) + .byte px(%1111110),px(%0111000),px(%0000000),px(%0000000),px(%0000000),px(%1111111),px(%0011111) + .byte px(%1111110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%0011111) + .byte px(%1111111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0111111) + .byte px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000011) + .byte px(%1100110),px(%0111001),px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111001) + .byte px(%1100111),px(%0011100),px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000001) + .byte px(%1100111),px(%1001110),px(%0111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001) + .byte px(%1100111),px(%1100111),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000001) + .byte px(%1100111),px(%1110011),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001) + .byte px(%1100111),px(%1111000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000001) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001) + .byte px(%1100111),px(%1001100),px(%1100110),px(%0110011),px(%1111111),px(%1111111),px(%1111001) + .byte px(%1100110),px(%0110011),px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%0011001) + .byte px(%1100111),px(%1001100),px(%1100110),px(%0110011),px(%0011001),px(%1001100),px(%1111001) + .byte px(%1100110),px(%0110011),px(%0011001),px(%1001100),px(%1100110),px(%0110011),px(%0011001) + .byte px(%1100111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111111),px(%1111001) + .byte px(%1110000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000000),px(%0000011) + + +;;; ============================================================ + +str_ii: + PASCAL_STRING "Apple ][" + +str_iiplus: + PASCAL_STRING "Apple ][+" + +str_iii: + PASCAL_STRING "Apple /// (emulation)" + +str_iie: + PASCAL_STRING "Apple //e" + +str_iie_enhanced: + PASCAL_STRING "Apple IIe (enhanced)" + +str_iie_card: + PASCAL_STRING "Apple IIe Card" + +str_iic: + PASCAL_STRING "Apple IIc" + +str_iic_plus: + PASCAL_STRING "Apple IIc Plus" + +str_iigs: + PASCAL_STRING "Apple IIgs" + +str_laser128: + PASCAL_STRING "Laser 128" + +;;; ============================================================ + +str_prodos_version: + PASCAL_STRING "ProDOS 0.0.0" + +str_slot_n: + PASCAL_STRING "Slot 0: " + +str_memory_prefix: + PASCAL_STRING "Memory: " + +str_memory_suffix: + PASCAL_STRING "K" + +memory:.word 0 + +;;; ============================================================ + +str_diskii: PASCAL_STRING "Disk II" +str_block: PASCAL_STRING "Generic Block Device" +str_smartport: PASCAL_STRING "SmartPort Device" +str_ssc: PASCAL_STRING "Super Serial Card" +str_80col: PASCAL_STRING "80 Column Card" +str_mouse: PASCAL_STRING "Mouse Card" +str_silentype: PASCAL_STRING "Silentype" +str_clock: PASCAL_STRING "Clock" +str_comm: PASCAL_STRING "Communications Card" +str_serial: PASCAL_STRING "Serial Card" +str_parallel: PASCAL_STRING "Parallel Card" +str_used: PASCAL_STRING "Used" +str_printer: PASCAL_STRING "Printer" +str_joystick: PASCAL_STRING "Joystick" +str_io: PASCAL_STRING "I/O Card" +str_modem: PASCAL_STRING "Modem" +str_audio: PASCAL_STRING "Audio Card" +str_storage: PASCAL_STRING "Mass Storage" +str_network: PASCAL_STRING "Network Card" +str_mockingboard: PASCAL_STRING "Mockingboard" +str_unknown: PASCAL_STRING "(unknown)" +str_empty: PASCAL_STRING "(empty)" + +;;; ============================================================ + +str_cpu_prefix: PASCAL_STRING " CPU: " +str_6502: PASCAL_STRING "6502" +str_65C02: PASCAL_STRING "65C02" +str_658xx: PASCAL_STRING "658xx" + +;;; ============================================================ + +model_str_ptr: .addr 0 +model_pix_ptr: .addr 0 + +line1: DEFINE_POINT 0, 37 +line2: DEFINE_POINT da_width, 37 + +pos_slot1: DEFINE_POINT 45, 50 +pos_slot2: DEFINE_POINT 45, 61 +pos_slot3: DEFINE_POINT 45, 72 +pos_slot4: DEFINE_POINT 45, 83 +pos_slot5: DEFINE_POINT 45, 94 +pos_slot6: DEFINE_POINT 45, 105 +pos_slot7: DEFINE_POINT 45, 116 + +slot_pos_table: + .addr 0, pos_slot1, pos_slot2, pos_slot3, pos_slot4, pos_slot5, pos_slot6, pos_slot7 + +;;; ============================================================ + +model_pos: DEFINE_POINT 150, 12 +pdver_pos: DEFINE_POINT 150, 23 +mem_pos: DEFINE_POINT 150, 34 + +.proc event_params +kind: .byte 0 +;;; EventKind::key_down +key := * +modifiers := * + 1 +;;; EventKind::update +window_id := * +;;; otherwise +xcoord := * +ycoord := * + 2 + .res 4 +.endproc + +.proc findwindow_params +mousex: .word 0 +mousey: .word 0 +which_area: .byte 0 +window_id: .byte 0 +.endproc + +.proc trackgoaway_params +clicked: .byte 0 +.endproc + +.proc dragwindow_params +window_id: .byte 0 +dragx: .word 0 +dragy: .word 0 +moved: .byte 0 +.endproc + +.proc winport_params +window_id: .byte da_window_id +port: .addr grafport +.endproc + +.proc grafport +viewloc: DEFINE_POINT 0, 0 +mapbits: .word 0 +mapwidth: .word 0 +cliprect: DEFINE_RECT 0, 0, 0, 0 +pattern: .res 8, 0 +colormasks: .byte 0, 0 +penloc: DEFINE_POINT 0, 0 +penwidth: .byte 0 +penheight: .byte 0 +penmode: .byte 0 +textback: .byte 0 +textfont: .addr 0 +.endproc + + +;;; ============================================================ +;;; Per Tech Note: Apple II Miscellaneous #7: Apple II Family Identification, +;;; and c/o JohnMBrooks + +;;; Machine $FBB3 $FB1E $FBC0 $FBDD $FBBE $FBBF +;;; ----------------------------------------------------------------------------- +;;; Apple ][ $38 [$AD] [$60] [$2F] +;;; Apple ][+ $EA $AD [$EA] [$EA] +;;; Apple /// (emulation) $EA $8A +;;; Apple IIe $06 [$AD] $E0 [$00] +;;; Apple IIe (enhanced) $06 [$AD] $E0 [$00] +;;; Apple IIe Option Card $06 [$AD] $E0 $02 $00 +;;; Apple IIc $06 $00 $FF +;;; Apple IIc (3.5 ROM) $06 $00 $00 +;;; Apple IIc (Org. Mem. Exp.) $06 $00 $03 +;;; Apple IIc (Rev. Mem. Exp.) $06 $00 $04 +;;; Apple IIc Plus $06 $00 $05 +;;; Apple IIgs $06 [$4C] $E0 (and SEC, JSR $FE1F, CC=IIgs) +;;; Laser 128 $06 $AC [$E0] +;;; +;;; (Values in [] are for reference, not needed for compatibility check) + +.scope model + ii := 0 + iiplus := 1 + iie := 2 + iie_enhanced := 3 + iic := 4 + iic_plus := 5 + iigs := 6 + iie_card := 7 + iii := 8 + laser128 := 9 + LAST := 10 +.endscope + +model_str_table: + .addr str_ii, str_iiplus, str_iie, str_iie_enhanced + .addr str_iic, str_iic_plus, str_iigs, str_iie_card + .addr str_iii, str_laser128 + +model_pix_table: + .addr iie_bitmap, iie_bitmap, iie_bitmap, iie_bitmap + .addr iic_bitmap, iic_bitmap, iigs_bitmap, iie_card_bitmap + .addr iii_bitmap, laser128_bitmap + +.proc identify_model + ;; Read from ROM + lda ROMIN2 + + ;; ][, ][+ or /// + lda $FBB3 + cmp #$38 + bne :+ + lda #model::ii + bpl done +: cmp #$EA + bne iie_or_later + lda $FB1E + cmp #$AD + bne :+ + lda #model::iiplus + bpl done +: lda #model::iii + bpl done + +iie_or_later: + lda $FBC0 + beq iic_or_plus + + ;; IIe, IIe card, IIgs or Laser 128 + lda $FB1E + cmp #$AC + bne :+ + lda #model::laser128 + bpl done +: sec + jsr ID_BYTE_FE1F + bcs :+ + lda #model::iigs + bpl done +: lda $FBDD + cmp #$02 + bne :+ + lda #model::iie_card + bpl done +: lda #model::iie + bpl done + +iic_or_plus: + lda $FBBF + cmp #5 + bne :+ + lda #model::iic + bpl done +: lda #model::iic_plus + ;; fall through... + +done: asl + tax + copy16 model_str_table,x, model_str_ptr + copy16 model_pix_table,x, model_pix_ptr + + ;; Read from LC RAM + lda LCBANK1 + lda LCBANK1 + rts +.endproc + + + +;;; ============================================================ + +;;; KVERSION Table +;;; $00 1.0.1 +;;; $01 1.0.2 +;;; $01 1.1.1 +;;; $04 1.4 +;;; $05 1.5 +;;; $07 1.7 +;;; $08 1.8 +;;; $08 1.9 +;;; $21 2.0.1 +;;; $23 2.0.3 +;;; $24 2.4.x + +.proc identify_prodos_version + ;; Read ProDOS version field from global page in main + sta RAMRDOFF + sta RAMWRTOFF + lda KVERSION + sta RAMRDON + sta RAMWRTON + + cmp #$24 + bcs v_2x + cmp #$20 + bcs v_20x + + ;; $00...$08 are 1.x (roughly) +v_1x: and #$0F + clc + adc #'0' + sta str_prodos_version + 10 + lda #'1' + sta str_prodos_version + 8 + lda #10 + sta str_prodos_version ; length + bne done + + ;; $20...$23 are 2.0.x (roughly) +v_20x: and #$0F + clc + adc #'0' + sta str_prodos_version + 12 + lda #'0' + sta str_prodos_version + 10 + lda #'2' + sta str_prodos_version + 8 + lda #12 + sta str_prodos_version ; length + bne done + + ;; $24...??? are 2.x (so far?) +v_2x: and #$0F + clc + adc #'0' + sta str_prodos_version + 10 + lda #'2' + sta str_prodos_version + 8 + lda #10 + sta str_prodos_version ; length + bne done + +done: rts +.endproc + +;;; ============================================================ + +.proc init + sta ALTZPON + lda LCBANK1 + lda LCBANK1 + + jsr identify_model + jsr identify_prodos_version + jsr identify_memory + + MGTK_CALL MGTK::OpenWindow, winfo + jsr draw_window + MGTK_CALL MGTK::FlushEvents + ;; fall through +.endproc + +.proc input_loop + MGTK_CALL MGTK::GetEvent, event_params + bne exit + lda event_params::kind + cmp #MGTK::EventKind::button_down ; was clicked? + beq handle_down + cmp #MGTK::EventKind::key_down ; any key? + beq handle_key + jmp input_loop +.endproc + +.proc exit + MGTK_CALL MGTK::CloseWindow, winfo + DESKTOP_CALL DT_REDRAW_ICONS + rts ; exits input loop +.endproc + +;;; ============================================================ + +.proc handle_key + lda event_params::key + cmp #CHAR_ESCAPE + beq exit + cmp #'E' + bne input_loop + jmp handle_egg +.endproc + +;;; ============================================================ + +.proc handle_down + copy16 event_params::xcoord, findwindow_params::mousex + copy16 event_params::ycoord, findwindow_params::mousey + MGTK_CALL MGTK::FindWindow, findwindow_params + bne exit + lda findwindow_params::window_id + cmp winfo::window_id + bne input_loop + lda findwindow_params::which_area + cmp #MGTK::Area::close_box + beq handle_close + cmp #MGTK::Area::dragbar + beq handle_drag + jmp input_loop +.endproc + +;;; ============================================================ + +.proc handle_close + MGTK_CALL MGTK::TrackGoAway, trackgoaway_params + lda trackgoaway_params::clicked + beq input_loop + bne exit +.endproc + +;;; ============================================================ + +.proc handle_drag + copy winfo::window_id, dragwindow_params::window_id + copy16 event_params::xcoord, dragwindow_params::dragx + copy16 event_params::ycoord, dragwindow_params::dragy + MGTK_CALL MGTK::DragWindow, dragwindow_params + lda dragwindow_params::moved + bpl :+ + + ;; Draw DeskTop's windows + sta RAMRDOFF + sta RAMWRTOFF + jsr JUMP_TABLE_REDRAW_ALL + sta RAMRDON + sta RAMWRTON + + ;; Draw DA's window + jsr draw_window + + ;; Draw DeskTop icons + DESKTOP_CALL DT_REDRAW_ICONS + +: jmp input_loop + +.endproc + +;;; ============================================================ + +.proc handle_egg + lda egg + asl + tax + copy16 model_str_table,x, model_str_ptr + copy16 model_pix_table,x, model_pix_ptr + + inc egg + lda egg + cmp #model::LAST + bne :+ + lda #0 + sta egg + +: jsr clear_window + jsr draw_window +done: jmp input_loop + +egg: .byte 0 +.endproc + +;;; ============================================================ + +.proc clear_window + MGTK_CALL MGTK::GetWinPort, winport_params + cmp #MGTK::Error::window_obscured + bne :+ + rts + +: MGTK_CALL MGTK::SetPort, grafport + MGTK_CALL MGTK::PaintRect, grafport::cliprect + rts +.endproc + +;;; ============================================================ + +.proc draw_window + ptr := $06 + + MGTK_CALL MGTK::GetWinPort, winport_params + cmp #MGTK::Error::window_obscured + bne :+ + rts + +: MGTK_CALL MGTK::SetPort, grafport + MGTK_CALL MGTK::HideCursor + + copy16 model_pix_ptr, bits_addr + MGTK_CALL MGTK::PaintBits, $0000, bits_addr + + MGTK_CALL MGTK::MoveTo, model_pos + ldax model_str_ptr + jsr draw_pascal_string + + MGTK_CALL MGTK::MoveTo, pdver_pos + addr_call draw_pascal_string, str_prodos_version + + MGTK_CALL MGTK::SetPenMode, penmode + MGTK_CALL MGTK::MoveTo, line1 + MGTK_CALL MGTK::LineTo, line2 + + MGTK_CALL MGTK::MoveTo, mem_pos + addr_call draw_pascal_string, str_memory_prefix + addr_call draw_pascal_string, str_from_int + addr_call draw_pascal_string, str_memory_suffix + addr_call draw_pascal_string, str_cpu_prefix + jsr cpuid + jsr draw_pascal_string + + lda #7 + sta slot + lda #1<<7 + sta mask + +loop: lda slot + asl + tax + copy16 slot_pos_table,x, slot_pos + MGTK_CALL MGTK::MoveTo, 0, slot_pos + lda slot + clc + adc #'0' + sta str_slot_n + 6 + addr_call draw_pascal_string, str_slot_n + + ;; Check ProDOS slot bit mask + sta RAMRDOFF + lda SLTBYT + sta RAMRDON + and mask + bne check + + ldax #str_empty + jsr draw_pascal_string + jmp next + +check: lda slot + jsr probe_slot + jsr draw_pascal_string + +next: lsr mask + dec slot + bne loop + + MGTK_CALL MGTK::ShowCursor + rts + +slot: .byte 0 +mask: .byte 0 +penmode:.byte MGTK::notpencopy +.endproc + + +;;; ============================================================ +;;; Firmware Detector: Slot # in A, returns string ptr in A,X +;;; +;;; Uses a variety of sources: +;;; * TechNote ProDOS #21: Identifying ProDOS Devices +;;; * TechNote Miscellaneous #8: Pascal 1.1 Firmware Protocol ID Bytes +;;; * "ProDOS BASIC Programming Examples" disk + +.proc probe_slot + ptr := $6 + + ;; Point ptr at $Cn00 + clc + adc #$C0 + sta ptr+1 + lda #0 + sta ptr + + ;; Get Firmware Byte +.macro getfwb offset + ldy #offset + lda (ptr),y +.endmacro + + ;; Compare Firmware Byte +.macro cmpfwb offset, value + getfwb offset + cmp #value +.endmacro + +.macro result arg + ldax #arg + rts +.endmacro + +;;; --------------------------------------------- +;;; Per Miscellaneous Technical Note #8 +;;; ProDOS and SmartPort Devices + + cmpfwb $01, $20 ; $Cn01 == $20 ? + bne notpro + + cmpfwb $03, $00 ; $Cn03 == $00 ? + bne notpro + + cmpfwb $05, $03 ; $Cn05 == $03 ? + bne notpro + +;;; Per ProDOS Technical Note #21 + cmpfwb $FF, $00 ; $CnFF == $00 ? + bne :+ + result str_diskii +: + + cmpfwb $07, $00 ; $Cn07 == $00 ? + beq :+ + result str_block + +;;; TODO: Follow SmartPort Technical Note #4 +;;; and identify specific device type via STATUS call +: + result str_smartport +notpro: +;;; --------------------------------------------- +;;; Per Miscellaneous Technical Note #8 +;;; Pascal 1.1 Devices + + cmpfwb $05, $38 ; $Cn05 == $38 ? + bne notpas + + cmpfwb $07, $18 ; $Cn07 == $18 ? + bne notpas + + cmpfwb $0B, $01 ; $Cn0B == $01 ? + bne notpas + + getfwb $0C ; $Cn0C == .... + +.macro sig byte, arg + cmp #byte + bne :+ + result arg +: +.endmacro + + sig $31, str_ssc + sig $88, str_80col + sig $20, str_mouse + +notpas: +;;; --------------------------------------------- +;;; Based on ProDOS BASIC Programming Examples + +;;; Silentype + cmpfwb 23, 201 + bne :+ + cmpfwb 55, 207 + bne :+ + cmpfwb 76, 234 + bne :+ + result str_silentype +: + +;;; Clock + cmpfwb 0, 8 + bne :+ + cmpfwb 1, 120 + bne :+ + cmpfwb 2, 40 + bne :+ + result str_clock +: + +;;; Communications Card + cmpfwb 5, 24 + bne :+ + cmpfwb 7, 56 + bne :+ + result str_comm +: + +;;; Serial Card + cmpfwb 5, 56 + bne :+ + cmpfwb 7, 24 + bne :+ + result str_serial +: + +;;; Parallel Card + cmpfwb 5, 72 + bne :+ + cmpfwb 7, 72 + bne :+ + result str_parallel +: + +;;; Generic Devices + cmpfwb 11, 1 + bne :+ + getfwb 12 + clc + ror + ror + ror + ror + + cmp #0 + bne :+ + result str_used +: + cmp #1 + bne :+ + result str_printer +: + cmp #2 + bne :+ + result str_joystick +: + cmp #3 + bne :+ + result str_io +: + cmp #4 + bne :+ + result str_modem +: + cmp #5 + bne :+ + result str_audio +: + cmp #6 + bne :+ + result str_clock +: + cmp #7 + bne :+ + result str_storage +: + cmp #8 + bne :+ + result str_80col +: + cmp #9 + bne :+ + result str_network +: + jsr detect_mockingboard + bcc :+ + result str_mockingboard +: + result str_unknown +.endproc + + +;;; Detect Mockingboard +;;; Assumes $06 points at $Cn00, returns carry set if found + +.proc detect_mockingboard + ptr := $06 + tmp := $08 + + ldy #4 ; $Cn04 + ldx #2 ; try 2 times + +loop: lda (ptr),Y ; 6522 Low-Order Counter + sta tmp ; read 8 cycles apart + lda (ptr),Y + + sec ; compare counter offset + sbc tmp + cmp #($100 - 8) + bne fail + dex + bne loop + +found: sec + rts + +fail: clc + rts +.endproc + +;;; ============================================================ +;;; Update str_memory with memory count in kilobytes + +.proc identify_memory + copy16 #0, memory + jsr check_ramworks_memory + sty memory ; Y is number of 64k banks + cpy #0 ; 0 means 256 banks + bne :+ + inc memory+1 +: inc16 memory ; Main 64k memory + asl16 memory ; * 64 + asl16 memory + asl16 memory + asl16 memory + asl16 memory + asl16 memory + ldax memory + jsr int_to_string +.endproc + +;;; ============================================================ +;;; Calculate RamWorks memory; returns number of banks in Y +;;; (256 banks = 0, since there must be at least 1) +;;; Note the bus floats for RamWorks RAM when the bank has no RAM, +;;; or bank selection may wrap to an earlier bank. +;;; RamWorks-style cards are not guaranteed to have contiguous banks. +;;; a user can install 64Kb or 256Kb chips in a physical bank, in the +;;; former case, a gap in banks will appear. Additionally, the piggy +;;; back cards may not have contiguous banks depending on capacity +;;; and installed chips. +;;; AE RamWorks cards can only support 8M max (banks $00-$7F), but +;;; the various emulators support 16M max (banks $00-$FF). +;;; +;;; If RamWorks is not present, bank switching is a no-op and the +;;; same regular 64Kb AUX bank is present throughout the test; this +;;; will be handled by an invalid signature check for other banks. +.proc check_ramworks_memory + sigb0 := $00 + sigb1 := $01 + + ;; DAs are loaded with $1C00 as the io_buffer, so + ;; $1C00-$1FFF MAIN is free. + buf0 := DA_IO_BUFFER + buf1 := DA_IO_BUFFER + $100 + + ;; Run from clone in main memory + php + sei ; don't let interrupts happen while the memory map is munged + + sta RAMRDOFF + sta RAMWRTOFF + + ;; Assumes ALTZPON on entry/exit + RWBANK := $C073 + + ;; Iterate downwards (in case unpopulated banks wrap to earlier ones), + ;; saving bytes and marking each bank. + ldx #255 ; bank we are checking +: stx RWBANK + copy sigb0, buf0,x ; preserve bytes + copy sigb1, buf1,x + txa ; bank num as first signature + sta sigb0 + eor #$FF ; complement as second signature + sta sigb1 + dex + cpx #255 + bne :- + + ;; Iterate upwards, tallying and restoring valid banks. + ldx #0 ; bank we are checking + ldy #0 ; populated bank count +loop: stx RWBANK ; select bank + txa + cmp sigb0 ; verify first signature + bne next + eor #$FF + cmp sigb1 ; verify second signature + bne next + iny ; match - count it, and restore + copy buf0,x, sigb0 + copy buf1,x, sigb1 +next: inx ; next bank + bne loop ; if we hit 256 banks, make sure we exit + + ;; Switch back to RW bank 0 (normal aux memory) + lda #0 + sta RWBANK + + ;; Back to executing from aux memory + sta RAMRDON + sta RAMWRTON + plp ; restore interrupt state + rts +.endproc + +;;; ============================================================ + +.proc draw_pascal_string + params := $6 + textptr := $6 + textlen := $8 + + stax textptr + ldy #0 + lda (textptr),y + beq exit + sta textlen + inc16 textptr + MGTK_CALL MGTK::DrawText, params +exit: rts +.endproc + +;;; ============================================================ + +str_from_int: + PASCAL_STRING "000000" + +.proc int_to_string + stax value + + ;; Fill buffer with spaces + ldx #6 + lda #' ' +: sta str_from_int,x + dex + bne :- + + lda #0 + sta nonzero_flag + ldy #0 ; y = position in string + ldx #0 ; x = which power index is subtracted (*2) + + ;; For each power of ten +loop: lda #0 + sta digit + + ;; Keep subtracting/incrementing until zero is hit +sloop: cmp16 value, powers,x + bpl subtract + + lda digit + bne not_pad + bit nonzero_flag + bmi not_pad + + ;; Pad with space + lda #' ' + bne :+ + ;; Convert to ASCII +not_pad: + clc + adc #'0' ; why not ORA $30 ??? + pha + lda #$80 + sta nonzero_flag + pla + + ;; Place the character, move to next +: sta str_from_int+2,y + iny + inx + inx + cpx #8 ; up to 4 digits (*2) via subtraction + beq done + jmp loop + +subtract: + inc digit + sub16 value, powers,x, value + jmp sloop + +done: lda value ; handle last digit + ora #'0' + sta str_from_int+2,y + rts + +powers: .word 10000, 1000, 100, 10 +value: .word 0 ; remaining value as subtraction proceeds +digit: .byte 0 ; current digit being accumulated +nonzero_flag: ; high bit set once a non-zero digit seen + .byte 0 +.endproc + +;;; ============================================================ +;;; Identify CPU - string pointer returned in A,X + +.proc cpuid + sed + lda #$99 + clc + adc #$01 + cld + bmi p6502 + clc + .pushcpu + .setcpu "65816" + sep #%00000001 ; two-byte NOP on 65C02 + .popcpu + bcs p658xx + ; 65C02 + result str_65C02 +p6502: result str_6502 +p658xx: result str_658xx +.endproc + +;;; ============================================================ + +da_end = * +.assert * < $1B00, error, "DA too big" + ;; I/O Buffer starts at MAIN $1C00 + ;; ... but icon tables start at AUX $1B00