******************* * * * P.O.V. Info 125 * * * ******************* *********** * Options * *********** ; OPT l- ; Produce executable. OPT c+ ; Case sensitivity on. OPT d- ; Debug off. OPT m- ; Don't expand macros in a listing. OPT o+ ; All optimisations on. OPT ow+ ; All optimisation warnings on. OPT ow2- ; Don't report zero offset opts. OPT ow3- ; Don't report long to word opts. OPT p- ; Not position-independent code. OPT s- ; No symbol table in a listing. OPT t+ ; Type checking on. OPT w+ ; Warnings on. OPT x- ; Extended debug off. include "SYSTEMEQ.S" *********** * Equates * *********** TAB equ 9 LF equ 10 CR equ 13 ESC equ 27 BS equ 127 SCR_BASE equ $44e MAX_LINES equ 8000 MAX_FIND_LEN equ (80-11) ********** * Macros * ********** MoveCursorTo MACRO move.w \1,d0 move.w \2,d1 bsr calc_cursor_addr ENDM KeyRoutEntry MACRO dc.w \1 dc.l \2 ENDM SECTION TEXT ************* * * * Main code * * * ************* start lea clock,a0 .clear clr.w (a0)+ cmp.l #finish,a0 blt.s .clear bsr super_mode bsr disable_mj bsr wait_kbd bsr get_res bsr med_res bsr save_palette bsr set_palette bsr start_tune bsr setup bsr set_sky move.l SCR_BASE,cur_addr bsr process_text bsr show_title bsr redraw_screen .loop bsr process_key tst.b finished beq.s .loop bsr shutdown bsr stop_tune bsr restore_palette bsr old_res bsr enable_mj bsr user_mode .flush move.w #11,-(sp) trap #1 addq.w #2,sp tst.l d0 beq.s .exit move.w #7,-(sp) trap #1 addq.w #2,sp bra.s .flush .exit clr.w -(sp) trap #1 ************ * * * Routines * * * ************ wait_kbd move.w #-1,-(sp) move.w #11,-(sp) trap #13 addq.w #4,sp and.b #$f,d0 bne.s wait_kbd rts setup move.w sr,-(sp) or.w #$700,sr lea vector_bak,a0 move.l VBL_ISR,(a0)+ move.l KBD_ISR,(a0)+ move.l TimerB_ISR,(a0)+ lea mfp_bak,a0 move.b IERA,(a0)+ move.b IERB,(a0)+ move.b IMRA,(a0)+ move.b IMRB,(a0)+ move.b VR,(a0)+ move.b TBCR,(a0)+ move.b TBDR,(a0)+ move.l #new_vbl,VBL_ISR move.l #new_kbd,KBD_ISR move.l #raster,TimerB_ISR clr.b TBCR move.b #$01,IERA move.b #$01,IMRA move.b #$40,IERB move.b #$40,IMRB bclr.b #3,VR move.w (sp)+,sr rts shutdown move.w sr,-(sp) or.w #$700,sr lea vector_bak,a0 move.l (a0)+,VBL_ISR move.l (a0)+,KBD_ISR move.l (a0)+,TimerB_ISR lea mfp_bak,a0 move.b (a0)+,IERA move.b (a0)+,IERB move.b (a0)+,IMRA move.b (a0)+,IMRB move.b (a0)+,VR move.b (a0)+,TBCR move.b (a0)+,TBDR move.w (sp)+,sr rts vsync move.w #37,-(sp) trap #14 addq.w #2,sp rts get_res move.w #4,-(sp) trap #14 addq.w #2,sp move.w d0,res_bak rts med_res move.w #1,-(sp) move.l $44e.w,-(sp) move.l $44e.w,-(sp) move.w #5,-(sp) trap #14 add.w #12,sp rts old_res move.w res_bak,-(sp) move.l $44e.w,-(sp) move.l $44e.w,-(sp) move.w #5,-(sp) trap #14 add.w #12,sp rts save_palette movem.l Palette0,d0-d7 movem.l d0-d7,old_pal rts set_palette movem.l new_pal,d0-d1 movem.l d0-d1,Palette0 rts restore_palette movem.l old_pal,d0-d7 movem.l d0-d7,Palette0 rts disable_mj pea mj_off move.w #1,-(sp) move.w #25,-(sp) trap #14 addq.w #8,sp rts enable_mj pea mj_on move.w #1,-(sp) move.w #25,-(sp) trap #14 addq.w #8,sp rts super_mode clr.l -(sp) move.w #32,-(sp) trap #1 addq.w #6,sp move.l d0,save_stk rts user_mode move.l save_stk,-(sp) move.w #32,-(sp) trap #1 addq.w #6,sp rts new_vbl clr.w vsync_flag clr.b TBCR move.b #8,TBDR move.l #raster,TimerB_ISR move.b #8,TBCR bsr tune+8 rte raster move.w #$000,Palette2 clr.b TBCR move.b #1,TBDR move.b #8,TBCR move.w #$000,Palette0 move.l #(*+10),TimerB_ISR rte REPT (192-1) move.w #$000,Palette2 move.l #(*+10),TimerB_ISR rte ENDR clr.b TBCR rte set_sky lea sky_cols(pc),a0 lea raster(pc),a1 move.w #Palette2,d0 move.w #192-1,d1 .loop cmp.w (a1)+,d0 bne.s .loop move.w (a0)+,-4(a1) dbf d1,.loop rts *************** * Subroutines * *************** ***************** * * * Find routines * * * ***************** find MoveCursorTo #0,#11 ; Show message box. lea find_box_line1,a6 bsr special_line MoveCursorTo #0,#12 lea find_box_line2,a6 bsr special_line MoveCursorTo #0,#13 lea find_box_line3,a6 bsr special_line bsr.s input_find_text tst.b find_string ; Anything typed for search string? beq.s .no_string ; No! bsr do_search tst.b found ; Found string? bne.s .found ; Yes! MoveCursorTo #0,#12 ; No, show 'Not found!' message lea not_found_mess,a6 ; and sound a beep! bsr special_line bsr wait_for_key .found bsr redraw_screen rts .no_string bsr redraw_screen rts input_find_text clr.b key_val ; Clear key 'buffer'. lea find_string,a6 moveq #0,d7 ; Input character counter. MoveCursorTo #9,#12 ; Show previous search string. move.l a6,a5 .old_string move.b (a5)+,d0 ; Get char. beq.s .show_cursor ; If null then were at the end! bsr special_char ; Show char. addq.w #1,d7 ; Increment char counter. bra.s .old_string .show_cursor move.w d7,d0 ; Show cursor. add.w #9,d0 MoveCursorTo d0,#12 move.w #174,d0 bsr special_char move.w d7,d0 add.w #9,d0 MoveCursorTo d0,#12 .loop bsr wait_for_key bsr convert_to_ascii cmp.b #CR,d0 ; Return key? beq.s .done ; Yes! cmp.b #BS,d0 ; Backspace? beq.s .remove_char ; Yes! cmp.b #' ',d0 ; Is key a printable character? blt.s .loop ; No! cmp.b #'~',d0 bgt.s .loop ; No! .char cmp.w #MAX_FIND_LEN,d7 ; Yes, is string full? bge.s .full ; Yes! move.b d0,(a6,d7) ; Store char. bsr special_char ; Show it. addq.w #1,d7 ; Increment counter. bra.s .show_cursor .full bra.s .loop .remove_char tst.w d7 ; Is string empty? beq.s .loop ; Yes! move.w d7,d0 ; No, overwrite last char add.w #9,d0 ; with a space. MoveCursorTo d0,#12 moveq #' ',d0 bsr special_char subq.w #1,d7 ; Decrement counter. bra.s .show_cursor .done move.w d7,d0 ; Remove cursor. add.w #9,d0 MoveCursorTo d0,#12 moveq #' ',d0 bsr special_char clr.b (a6,d7) ; Terminate string. rts do_search clr.b found ; Not found! lea line_ptrs,a4 move.w top_line,d6 ; Search from top screen line. .start_line move.w d6,d0 ; Get current line's text lsl.w #2,d0 ; address from line move.l (a4,d0),a6 ; pointer table. move.l a6,d0 ; Is address valid? beq.s .not_found ; No! move.l a6,a3 .compare lea find_string,a5 move.l a3,a6 ; Address of next char in line. .loop move.b (a5)+,d1 ; End of search string? beq.s .found ; Yes, then found string! move.b (a6)+,d0 ; Get char from text. beq.s .next_line ; Is it end of line? cmp.b d1,d0 ; Is it same as search char? beq.s .loop ; Yes! cmp.b #'a',d1 ; If text char is lower case, blt.s .next_char ; make it upper case. cmp.b #'z',d1 bgt.s .next_char sub.b #'a'-'A',d1 cmp.b d1,d0 ; Is text char same as search char? beq.s .loop ; Yes! .next_char addq.w #1,a3 ; Move to next char in line. bra.s .compare ; No! .found st found ; Found it! move.w d6,top_line .not_found rts .next_line addq.w #1,d6 ; End of line reached, bra.s .start_line ; increment line number. ******************************************** * * * Move to different place in text routines * * * ******************************************** top_of_text tst.w top_line ; Is display already at beq.s .end ; top of text? clr.w top_line ; No, move it there! bsr redraw_screen .end rts bot_of_text move.w top_line,d0 ; Is display already at cmp.w max_lines,d0 ; bottom of text? bge.s .end ; Yes! move.w max_lines,top_line ; No, move it there! bsr redraw_screen .end rts page_up tst.w top_line ; Is display already at beq.s .end ; top of text? moveq #22-1,d0 ; No, move up 22 lines. .loop tst.w top_line ; Is display already at beq.s .done ; top of text? subq.w #1,top_line ; No, decrement top line. dbf d0,.loop .done bsr redraw_screen .end rts page_down move.w top_line,d0 ; Is display already at cmp.w max_lines,d0 ; bottom of text? bge.s .end ; Yes! moveq #22-1,d1 ; No, move it doen 22 lines. .loop move.w top_line,d0 ; Is display already at cmp.w max_lines,d0 ; bottom of text? bge.s .done ; Yes! addq.w #1,top_line ; No, increment top line! dbf d1,.loop .done bsr.s redraw_screen .end rts line_up tst.w top_line ; Is display already beq.s .end ; at top of text? subq.w #1,top_line ; No, decrement top line. bsr scroll_down MoveCursorTo #0,#1 ; Show new top line. move.w top_line,cur_line bsr.s draw_line .end rts line_down move.w top_line,d0 ; Is display already cmp.w max_lines,d0 ; at bottom of text? bge.s .end ; Yes! addq.w #1,top_line ; No, increment top line. bsr scroll_up MoveCursorTo #0,#23 ; Display new bottom line. move.w top_line,d0 add.w #22,d0 move.w d0,cur_line bsr.s draw_line .end rts ************************************ * * * Direct access to screen routines * * * ************************************ redraw_screen move.w top_line,cur_line ; Text line number. moveq #1,d7 ; Screen line number. .loop MoveCursorTo #0,d7 ; Show current line. bsr.s draw_line addq.w #1,cur_line ; Increment text line number. addq.w #1,d7 ; Increment screen line number. cmp.w #24,d7 ; At bottom of screen? blt.s .loop ; No! rts ; Yes! draw_line move.w cur_line,d0 lsl.w #2,d0 ; Get current line's text lea line_ptrs,a6 ; address from line move.l (a6,d0),a6 ; pointer table. move.l a6,d0 ; Is address valid? beq.s .done ; No! .loop move.b (a6)+,d0 ; Get char. beq.s .done ; If null then end of line. cmp.b #TAB,d0 bne.s .not_tab move.w cur_xpos,d1 addq.w #8,d1 and.w #$fff8,d1 sub.w cur_xpos,d1 subq.w #1,d1 .tabs moveq #' ',d0 bsr.s text_char ; Show char. dbf d1,.tabs .not_tab bsr.s text_char ; Show char. bra.s .loop .done cmp.w #80,cur_xpos ; Cursor past end of line? bge.s .end ; Yes! moveq #' ',d0 ; No, show a space. bsr.s text_char bra.s .done .end rts text_char and.w #$ff,d0 ; Only chars 0 to 255. lsl.w #3,d0 ; Get char pixel definition lea font,a0 ; in font table. add.w d0,a0 move.l cur_addr,a1 ; Get cursor screen address. moveq #0,d0 OFF set 0 REPT 8 ; Char is 8 lines high. move.b (a0)+,d0 ; Get pixel line definition. movep.w d0,OFF(a1) ; Blast it onto 2 plane screen. OFF set OFF+160 ENDR .cont addq.w #1,a1 ; Increment cursor screen move.w a1,d0 ; address - is it into and.w #1,d0 ; next 16 pixel column? bne.s .no_bump ; No! addq.w #2,a1 ; Yes, fix address! .no_bump move.l a1,cur_addr ; Store cursor screen address. addq.w #1,cur_xpos ; Increment cursor X position. rts special_line move.b (a6)+,d0 ; Get char. beq.s .done ; If null then end of line. bsr.s special_char ; Show char. bra.s special_line .done cmp.w #80,cur_xpos ; Cursor past end of line? bge.s .end ; Yes! moveq #' ',d0 ; No, show a space. bsr.s special_char bra.s .done .end rts special_char and.w #$ff,d0 ; Only chars 0 to 255. lsl.w #3,d0 ; Get char pixel definition lea font,a0 ; in font table. add.w d0,a0 move.l cur_addr,a1 ; Get cursor screen address. moveq #-1,d0 ; Ensure correct colour OFF set 0 ; data on screen. REPT 8 ; Char is 8 lines high. move.b (a0)+,d0 ; Get pixel line definition. movep.w d0,OFF(a1) ; Blast it onto 2 plane screen. OFF set OFF+160 ENDR addq.w #1,a1 ; Increment cursor screen move.w a1,d0 ; address - is it into and.w #1,d0 ; next 16 pixel column? bne.s .no_bump ; No! addq.w #2,a1 ; Yes, fix address! .no_bump move.l a1,cur_addr ; Store cursor screen address. addq.w #1,cur_xpos ; Increment cursor X position. rts calc_cursor_addr move.w d0,cur_xpos move.w d1,cur_ypos move.l SCR_BASE,a0 ; Get screen start address. mulu #(160*8),d1 ; Calc line offset. add.w d1,a0 move.w d0,d1 ; Calc X screen offset. and.w #$fffe,d1 add.w d1,d1 add.w d1,a0 and.w #1,d0 add.w d0,a0 move.l a0,cur_addr rts ************************** * * * Miscellaneous routines * * * ************************** quit st finished rts ********************* * * * Keyboard routines * * * ********************* wait_for_key btst.b #7,key_val ; Scan key pressed? bne.s wait_for_key ; No! bset.b #7,key_val ; Yes, no repeat. rts convert_to_ascii move.b key_val,d0 ; Get keyboard scan code. and.w #$7f,d0 ; Mask off top bit. move.b key_shift,d1 ; Get alt, ctrl & shft keys status. and.b #%00000011,d1 ; Either shift key held? beq.s .unshifted ; No! or.b #%10000000,d0 ; Yes, use 'shifted' table. .unshifted lea key_to_ascii,a0 move.b (a0,d0),d0 ; Get corresponding ascii key. rts process_key move.b key_shift,d0 ; Get alt, ctrl & shfts and.w #$f,d0 ; and keyboard scan code. lsl.w #8,d0 move.b key_val,d0 ; Key pressed? bmi.s .end ; No! lea key_routines,a0 .loop move.w (a0)+,d1 ; Get scan code. beq.s .end ; If null then end of list. move.l (a0)+,a1 ; Get routine address. cmp.w d1,d0 ; Scan codes same? bne.s .loop ; No! jmp (a1) ; Yes, jump to routine! .end rts *************************************************** * * * Convert raw ascii text to fast access structure * * * *************************************************** process_text lea text,a0 ; ASCII text. lea line_ptrs,a1 ; List of addresses of ; start of lines. clr.w max_lines .line move.l a0,(a1)+ ; Store address of ; start of line. addq.w #1,max_lines .loop move.b (a0)+,d0 ; Get char from ascii text. beq.s .done ; If null then end of text. cmp.b #CR,d0 ; If end of line values then bne.s .loop ; zero them and advance to clr.b -1(a0) ; next line. cmp.b #LF,(a0) bne.s .skip addq.w #1,a0 .skip bra.s .line .done rts ************************** * * * Scroll screen routines * * * ************************** scroll_up move.l SCR_BASE,a0 ; Start of screen. lea (160*8)(a0),a0 ; Skip top line. lea (160*8)(a0),a1 ; First line to be scrolled up. moveq #22-1,d0 .line OFF set 0 ; Fast move character screen. REPT 26 movem.l (a1)+,d1-d7/a2-a6 movem.l d1-d7/a2-a6,OFF(a0) OFF set OFF+(4*12) ENDR movem.l (a1)+,d1-d7/a2 movem.l d1-d7/a2,OFF(a0) lea (160*8)(a0),a0 dbf d0,.line rts scroll_down move.l SCR_BASE,a0 ; Start of screen. lea (160*8*22)(a0),a0 ; First line to be scrolled from. lea (160*8)(a0),a1 ; First line to be scrolled to. moveq #22-1,d0 .line OFF set 0 ; Fast move character line. REPT 26 movem.l (a0)+,d1-d7/a2-a6 movem.l d1-d7/a2-a6,OFF(a1) OFF set OFF+(4*12) ENDR movem.l (a0)+,d1-d7/a2 movem.l d1-d7/a2,OFF(a1) lea -(160*8*2)(a0),a0 lea -(160*8)(a1),a1 dbf d0,.line rts ***************************** * * * Setup & shutdown routines * * * ***************************** ******************************** * * * Show top & bottom text lines * * * ******************************** show_title MoveCursorTo #0,#0 ; Show top text line. lea header_text,a6 bsr special_line MoveCursorTo #0,#24 ; Show bottom text line. lea footer_text,a6 bsr special_line rts start_tune moveq #1,d0 bra tune stop_tune bsr tune+4 lea PSGreg,a0 move.l #$8080000,(a0) move.l #$9090000,(a0) move.l #$a0a0000,(a0) rts ******************************* * * * Keyboard interrupt routines * * * ******************************* new_kbd move.l d0,-(sp) .again move.b KBD_DATA,d0 .l_shft_m cmp.b #$2a,d0 ; Left shift (make)? bne.s .l_shft_b or.b #%00000001,key_shift .l_shft_b cmp.b #$aa,d0 ; Left shift (break)? bne.s .r_shft_m and.b #%11111110,key_shift .r_shft_m cmp.b #$36,d0 ; Right shift (make)? bne.s .r_shft_b or.b #%00000010,key_shift .r_shft_b cmp.b #$b6,d0 ; Right shift (break)? bne.s .ctrl_m and.b #%11111101,key_shift .ctrl_m cmp.b #$1d,d0 ; Control (make)? bne.s .ctrl_b or.b #%00000100,key_shift .ctrl_b cmp.b #$9d,d0 ; Control (break)? bne.s .alt_m and.b #%11111011,key_shift .alt_m cmp.b #$38,d0 ; Alternate (make)? bne.s .alt_b or.b #%00001000,key_shift .alt_b cmp.b #$b8,d0 ; Alternate (break)? bne.s .key and.b #%11110111,key_shift .key move.b d0,key_val btst.b #4,GPIP ; Another key in queue? beq .again ; Yes! move.l (sp)+,d0 rte ******************** * * * Palette routines * * * ******************** ******************************* * * * Wait for the vertical blank * * * ******************************* ********************************* * * * Routines to change resolution * * * ********************************* ****************************** * * * Disable & enable the mouse * * * ****************************** ***************** * * * Set cpu modes * * * ***************** ******************** * * * Initialised data * * * ******************** SECTION DATA mj_off dc.b $12,$1a mj_on dc.b $14,$08 new_pal dc.w $000, $006, $000, $fff font incbin "ST.SET" header_text dc.b " Info 125 coded by Boris /" dc.b " 'Pigs Might Fly' credits music - ripped by MUG U.K." dc.b 0 even footer_text dcb.b 29,' ' dc.b '"Persistence Of Vision"' dc.b 0 even find_box_line1 dc.b 0 find_box_line2 dc.b ' Find ?' find_box_line3 dc.b 0 even not_found_mess dcb.b 34,' ' dc.b 'Not found!',0 even key_to_ascii dc.b 0,ESC,'1234567890-=',BS,TAB ; Unshifted. dc.b 'qwertyuiop[]',CR,0,'as' dc.b 'dfghjkl;''`',0,'#zxcv' dc.b 'bnm,./',0,0,0,' ',0,0,0,0,0,0 dc.b 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0 dcb.b 16,0 dc.b '\',0,0,'()/*789456123' dc.b '0.',CR,0,0,0,0,0,0,0,0,0,0,0,0,0 dc.b 0,ESC,'!"œ$%^&*()_+',BS,TAB ; Shifted. dc.b 'QWERTYUIOP{}',CR,0,'AS' dc.b 'DFGHJKL:@_',0,'~ZXCV' dc.b 'BNM<>?',0,0,0,' ',0,0,0,0,0,0 dc.b 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0 dcb.b 16,0 dc.b '|',0,0,'()/*789456123' dc.b '0.',CR,0,0,0,0,0,0,0,0,0,0,0,0,0 key_routines KeyRoutEntry $0448,top_of_text ; Control & up arrow. KeyRoutEntry $0450,bot_of_text ; Control & down arrow. KeyRoutEntry $0248,page_up ; Left shift & up arrow. KeyRoutEntry $0250,page_down ; Left shift & down arrow. KeyRoutEntry $0148,page_up ; Right shift & up arrow. KeyRoutEntry $0150,page_down ; Right shift & down arrow. KeyRoutEntry $0048,line_up ; Up arrow. KeyRoutEntry $0050,line_down ; Right arrow. KeyRoutEntry $0821,find ; Alternate & 'f'. KeyRoutEntry $0001,quit ; Escape. dc.w 0 sky_cols incbin "SKY.RGB" tune incbin "TSC_CRED.THK" even text incbin "DISKLIST" ; Put your own file here. dc.b 0 even ********************** * * * Uninitialised data * * * ********************** SECTION BSS clock ds.w 1 vsync_flag ds.w 1 res_bak ds.w 1 old_pal ds.w 16 vector_bak ds.l 3 mfp_bak ds.b 7 even save_stk ds.l 1 finished ds.b 1 key_shift ds.b 1 key_val ds.b 1 found ds.b 1 even cur_xpos ds.w 1 cur_ypos ds.w 1 cur_addr ds.l 1 max_lines ds.w 1 cur_line ds.w 1 top_line ds.w 1 find_string ds.b (MAX_FIND_LEN+1) even line_ptrs ds.l MAX_LINES finish even