[comp.sources.atari.st] v02i055: coloremu -- Color emulator for mono screens

koreth%panarthea.ebay@sun.com (Steven Grimm) (07/21/89)

Submitted-by: f-leoe@ifi.uio.no (Lars-Erik 0sterud)
Posting-number: Volume 2, Issue 55
Archive-name: coloremu

[The binary will be posted to the binaries group.  The source is below.
 The submitter asks that someone try to speed this up if possible... -sg]

---- cut here ----
 MOVE.L 4(A7),A0
 MOVE.L #$8400,D6               ; 32K for the screen
 ADD.L $C(A0),D6                ; plus the usual space
 ADD.L $14(A0),D6
 ADD.L $1C(A0),D6
 MOVE.L D6,-(SP)                ; save length of program for later

 MOVE.W #4,-(SP)
 TRAP #14                       ; Get screen Resolution
 ADDQ.L #2,SP
 CMP.W #2,D0                    ; If monochrome then carry on
 BEQ monochrome
 MOVE.L (SP)+,D6                ; else tidy up the stack
 MOVE.W #0,-(SP)                ; return ok to,GEM
 TRAP #1                        ; Then exit back to desktop
monochrome:
 CLR.L -(SP)
 MOVE.W #32,-(SP)
 TRAP #1                        ; Enter supervisor mode
 ADDQ.L #6,SP
 MOVE.L D0,savestack            ; Save the supervisor stack

 PEA message                    ; Address of message
 MOVE.W #9,-(SP)                ; Print startup message
 TRAP #1
 ADDQ.L #6,SP
inloop:
 PEA input                      ; Adress of message
 MOVE.W #9,-(SP)                ; Print input message
 TRAP #1
 ADDQ.L #6,SP
 MOVE.W #1,-(SP)                ; Conin
 TRAP #1                        ; GemDos
 ADDQ.L #2,SP
 SUB.B #48,D0
 BLE inloop                     ; Too low  (<1)
 CMP.B #6,D0
 BGT inloop                     ; Too High (>6)
 MOVE.B D0,step                 ; Save speed
 SUB.L A5,A5
 MOVE.L $044E(A5),high          ; Set HIGH
 MOVE.L $B8,xbiospoke+2         ; Get the old XBIOS address and
 MOVE.L $70,vblankpoke+2        ; VBLANK and insert into new versions
 MOVE.W #0,count                ; Counter is set to zero
 LEA message,A2                 ; A2 = pos of text
 MOVE.L A2,D0                   ; A2 = start of free memory
 ADD.L #512,D0                  ; Force it to a 512 byte boundry
 AND.L #$FFFFFE00,D0
 MOVE.L D0,$044E(A5)            ; And that is the LOW screen
 MOVE.L D0,low                  ; Set LOW
 MOVE.L #whoops,$046E(A5)
 MOVE.W #$0000,-(SP)            ; Hardware and Software to low
 MOVE.L #-1,-(SP)
 MOVE.L #-1,-(SP)
 MOVE.W #5,-(SP)
 TRAP #14                       ; Set low resolution
whoops:
 ADD.L #12,SP
 MOVE.L $70,A0                  ; Save the old VBLANK
 MOVE.L #simple_vblank,$70      ; And set up mine
 MOVE.W #1,raster_flag          ; Set raster flag to 'not occured yet'
wait_raster:
 TST.W raster_flag              ; If still not occured
 BNE wait_raster                ; then loop until a vbl does occur
 MOVE.B #2,$FF8260              ; Back to HIGH hardware after VBL
 MOVE.L A0,$70
 MOVE.L #xbios,$B8              ; Set up the new XBIOS vector
 MOVE.L #vblank,$70             ; And the new VBLANK vector
 MOVE.L savestack,-(SP)         ; Restore the Supervisor stack
 MOVE.W #32,-(SP)               ; And go back to User mode
 TRAP #1
 ADDQ.L #6,SP
 MOVE.L (SP)+,D0                ; Tidy stack
 CLR.W -(SP)                    ; Exit ok for GEM
 MOVE.L D0,-(SP)                ; Length of program + data space
 MOVE.W #$31,-(SP)              ; terminate and stay resident (TSR)
 TRAP #1                        ; Finished this AUTO program

xbios:
 MOVEM.L A1/A2,-(SP)            ; Save A1 and A2
 MOVE.L SP,A2                   ; A2 = the stack
 ADD.L #8,A2                    ; offset over A1 and A2
 BTST #5,(A2)                   ; Test if called from user mode
 BNE notuser                    ; Skip if it is
 MOVE.L USP,A2                  ; Otherwise get A2 = User stack
 SUB.L #6,A2                    ; Offset it as if it were the SSP
notuser:
 MOVE.W $6(A2),D0               ; Get XBIOS instruction code
 CMP.W #2,D0                    ; If it is _PHYSBASE 
 BEQ physbase                   ; then jump to new PHYSBASE routine
 CMP.W #4,D0                    ; If it is _GETREZ 
 BEQ getrez                     ; then jump to new GETREZ routine
 CMP.W #5,D0                    ; If it is NOT _SETSCREEN
 BNE norm_xbios                 ; Then continue with the normal XBIOS
 MOVE.W #-1,16(A2)              ; Else alter rez.W to -1 (No change)
 MOVE.L 12(A2),D0               ; Get the ploc.L parameter
 CMP.L #-1,D0                   ; If it is -1 
 BEQ norm_xbios                 ; then continue with normal XBIOS
 MOVE.L D0,low                  ; Otherwise, new value goes to LOW
 MOVE.L #-1,12(A2)              ; Set ploc.L to -1 (no change)
 BRA norm_xbios                 ; then norm BIOS deals with lloc.L

physbase:
 MOVE.L low,D0                  ; Get address of LOW screen
 MOVEM.L (SP)+,A1/A2            ; Tidy stack
 RTE                            ; Return LOW screen location

getrez:
 MOVE.W #0,D0                   ; Pretend we are in LOW resolution
 MOVEM.L (SP)+,A1/A2            ; Tidy the stack
 RTE                            ; Return code for LOW resolution

norm_xbios:
 MOVEM.L (SP)+,A1/A2            ; Tidy the stack up
xbiospoke:
 JMP $0.L                       ; And jump into the normal XBIOS

vblank:
 TST.W $43E                     ; Test flock system variable
 BNE vblankpoke                 ; No update if drive active

 MOVEM.L D0-D7/A0-A6,-(SP)      ; Save all registers
 CLR.L D0
 MOVE.B $FF8201,D0              ; Video base high
 LSL.L #8,D0                    ; times 256
 MOVE.B $FF8203,D0              ; Plus video base low
 LSL.L #8,D0                    ; All times 256
 MOVE.L D0,A3                   ; Is the address of the Real screen
 MOVE.L low,A2                  ; A0 = virtual LOW screen
 MOVE.L high,A1                 ; A1 = real HIGH screen
 CMP.L A1,A3                    ; Check if the real screen has moved
 BEQ screenok                   ; Skip this if not
 MOVE.L A3,A2                   ; Get the new real screen address
 MOVE.L A2,low                  ; Set LOW From this
 MOVE.L A1,D0                   ; And put the real screen back
 LSR.L #8,D0                    ; to its origional position
 MOVE.B D0,$FF8203
 LSR.L #8,D0
 MOVE.B D0,$FF8201

screenok:
 MOVE.L count,D2                ; How far did we do last time
 ADD.L D2,A1                    ; Move to this spot
 ADD.L D2,A2
 MOVE.B step,D3                 ; Get preset speed

mainloop:
 ADD.L #160,D2                  ; 160 bytes / color line
 CMP.L #32000,D2                ; 32000 bytes / screen
 BNE go_on
 CLR.W D2                       ; Start at the top once more
 MOVE.L high,A1
go_on:
 MOVE.B #20,D7                  ; 20 times / line
lineloop:
 ADDQ.L #4,A2
 MOVE.W (A2)+,D5
 MOVE.W (A2)+,D4
 MOVE.B #4,D0                   ; 4 times / color-byte
wordloop:
 ROXL.W #1,D4                   ; 4 color pixels
 ROXL.B #1,D6                   ; to one mono-byte
 ROXL.W #1,D5
 ROXL.B #1,D6
 ROXL.W #1,D4                   ; 2nd pixel
 ROXL.B #1,D6
 ROXL.W #1,D5
 ROXL.B #1,D6
 ROXL.W #1,D4                   ; 3rd pixel
 ROXL.B #1,D6
 ROXL.W #1,D5
 ROXL.B #1,D6
 ROXL.W #1,D4                   ; 4th pixel
 ROXL.B #1,D6
 ROXL.W #1,D5
 ROXL.B #1,D6

 MOVE.B D6,80(A1)               ; Set mono-byte  (low  line)
 MOVE.B D6,(A1)+                ; Set mono-byte  (high line)
 SUBQ.B #1,D0
 BNE wordloop
 SUBQ.B #1,D7
 BNE lineloop
 ADD.L #80,A1
 SUBQ.B #1,D3
 BNE mainloop

 MOVE.L D2,count
 MOVEM.L (SP)+,D0-D7/A0-A6      ; Restore all registers
vblankpoke:
 JMP $0.L                       ; Jump to normal VBLANK routine

simple_vblank:
 CLR.W raster_flag              ; Indicate a Vertical blank has occured
 RTE

 ALIGN.W

savestack:   DC.L 0
low:         DC.L 0             ; Base address of LOW screen
high:        DC.L 0             ; Base address of HIGH screen
count:       DC.L 0             ; Count so far
raster_flag: DC.W 0             ; Flag cleared every raster (tempory)
step:        DC.B 0             ; Speed (counts / vblank)

message:
 DC.B 27,'E',10,'  The Color Emulator v 1.0',13,10,10
 DC.B '  Should be in AUTO Folder',13,10
 DC.B '  Will run with any TOS',13,10,10
 DC.B '  Author:  Lars-Erik 2sterud',13,10,10
 DC.B '  Adress:  2kriveien 39',13,10
 DC.B '           N-1349 Rykkinn',13,10
 DC.B '           NORWAY',13,10,10
 DC.B '  Phone:   +47 2 13 15 71',13,10
 DC.B '  BBS:     +47 2 13 26 59',13,10,10
 DC.B '  Email:   leoe',64,'ifi.uio.no',13,10
 DC.B '           f-leoe',64,'ifi.uio.no',13,10,10,0

input:
 DC.B 13,10
 DC.B '  Enter update-speed (1 to 6): ',0

 END