send msdos,,d:\output ;Windows BITMAP creator: ;/''''''''''''''''''''''\ ;+ (c) 1993 Simon Cooke + ;\,,,,,,,,,,,,,,,,,,,,,,/ ;Works on currently displayed screen. Stores result in pages ;3&4... ;TO USE: ;------- ; Load in screen using 'LOAD "filenamexx"SCREEN$' ; SAVE "filenm.BMP" CODE 65536,USR 32768 ; an that's it... ORG &8000 ;Code length to be saved out from &8000: palette: EQU &55D8 ;Address of CLUT in sys.vars vmpr: EQU &FC ;Video paging port lmpr: EQU &FA ;Low section paging port hmpr: EQU &FB ;High section paging port bmp.page: EQU 3+32 ;page to store BMP in... bmp.start: EQU &0000 ;start address of BMP start: DI IN A,(lmpr) LD (low.page+1),A ;Store original BASIC values LD (sp.store+1),SP;for restoration later... LD SP,0 ;Self-modifying... IN A,(vmpr) ;Find current video setting AND 31 ;strip mode bits OR 32 ;Format for use in LMPR LD (vid.page+1),A ;store using self-modifying ;code LD HL,palette ;Copy palette to buffer LD DE,palette.store LD BC,20 LDIR IN A,(vmpr) AND 96 ;Strip video MODE bits LD (video.mode+1),A CALL set.bmp.mode4 ;RETURNS with video mode in A OR A ;test if a=0 JP Z,convert1to4 ;if mode 1, convert to mode 4 CP 32 JP Z,convert2to4 ;if mode 2, convert to mode 4 PUSH AF ;copy mode 3 or 4 picture to CALL copy.pic ;buffer, line 191 first, line POP AF ;0 last... CP 64 ;if mode 3, store as mode 3 JP Z,mode3stash ;After mode1 or 2 conversion, routine is re-entered here... mode4stash: LD HL,palette.store ;convert palette to RGB values from LD B,16 ;SAM CLUT format... CALL palette.conv LD A,bmp.page ;page in BMP dump address... OUT (lmpr),A LD DE,bmp.start+54 LD HL,palette.bgr ;copy palette to bmp LD BC,64 ;(16 colours) LDIR mode3.reentry: LD (headersize),DE ;store headersize (means that BMP ;dump address must start at 0 in a page) LD HL,bit.map.buffer;store pixel map LD BC,24576 LDIR LD (filesize),DE ;entire filesize... LD HL,bmp.header ;copy header to bmp page LD DE,bmp.start LD BC,54 LDIR LD BC,(filesize) JP ret.to.basic mode3stash: LD HL,palette.store+16 ;Offset to mode3 palette LD B,4 CALL palette.conv LD A,bmp.page OUT (lmpr),A LD DE,bmp.start+54 LD HL,palette.bgr ;copy palette to bmp LD BC,16 ;(4 colours) LDIR JP mode3.reentry ;Copy picture from screen to buffer, mirrored in y axis ;------------------------------------------------------ ;(only for modes 3 and 4) copy.pic: vid.page: LD A,&00 OUT (lmpr),A LD HL,191*128 ;line 191 of screen address LD DE,bit.map.buffer LD B,192 ;192 lines copy.loop: PUSH BC LD BC,128 LDIR DEC H POP BC DJNZ copy.loop RET ;Convert MODE 2 picture to MODE 4 picture... ;------------------------------------------- ;Mode 2 display layout is 256x192 2bit -- either set or reset, to give the ;foreground/background status, with a 32x192 attribute map holding values ;for which of the 16 CLUT colors the foreground and background are... ;Converts to MODE 4 (256x192, 4 bit) convert2to4: LD A,(vid.page+1) OUT (lmpr),A LD DE,bit.map.buffer LD B,192 conv24loop: LD C,0 LD A,B CALL find.y.mode2 PUSH HL LD L,0 LD H,B SRL H RR L SRL H RR L SRL H RR L SET 5,H PUSH HL POP IX POP HL conv24loop2: PUSH BC CALL expand.attrib LD A,(HL) CALL expand.byte INC HL INC IX POP BC INC C LD A,C CP 32 JR NZ,conv24loop2 LD A,B DEC B OR A JR NZ,conv24loop JP mode4stash ;Convert MODE 1 picture to MODE 4 picture... ;------------------------------------------- ;Similar to Mode 2, except the ATTRIBUTE map is 32x24 (8x8 characters instead ;of mode 2's 8x1 characters). The display is also arranged in a seemingly ;haphazard manner -- this is because it is a SPECTRUM (Timex 2000 I think) ;display emulation mode... convert1to4: LD A,(vid.page+1) OUT (lmpr),A LD DE,bit.map.buffer LD B,192 conv14loop: LD C,0 LD A,B CALL find.y.spec ;calculate address for next line -- SPECTRUM ;display arrangement makes this complex. PUSH HL PUSH DE LD A,B AND %11111000 LD L,A LD H,0 ADD HL,HL ADD HL,HL LD DE,6144 ADD HL,DE PUSH HL POP IX POP DE POP HL conv14loop2: PUSH BC CALL expand.attrib LD A,(HL) CALL expand.byte INC HL INC IX POP BC INC C LD A,C CP 32 JR NZ,conv14loop2 DJNZ conv14loop JP mode4stash ;Convert MODE 1 or 2 bitmap to MODE 4 nybbles ;-------------------------------------------- expand.byte: PUSH HL LD A,(HL) LD L,A LD H,4 exp.loop: XOR A CALL expansion SLA L ADD A,A ADD A,A ADD A,A ADD A,A CALL expansion SLA L LD (DE),A INC DE DEC H JR NZ,exp.loop POP HL RET ;Convert bit 7 to a nybble... ;---------------------------- expansion: BIT 7,L JR Z,paper ink: OR B RET paper: OR C RET ;Convert attribute value to MODE 4 expansion values: ;--------------------------------------------------- ;Enter with IX pointing to attribute address. ;Exits with B holding INK expansion, C holding PAPER expansion ; A is corrupted on exit expand.attrib: LD A,(IX+0) AND %01000000 LD C,A ADD A,A SRL C SRL C SRL C OR C LD C,A ;put bright as PUSH AF LD A,(IX+0) AND %00111000 SRL A SRL A SRL A OR C LD C,A ;put paper in c with bright LD A,(IX+0) AND %00000111 LD B,A POP AF OR B LD B,A ;ink in b with bright RET ;Convert y coord to SPECCY (MODE 1) address... ;--------------------------------------------- find.y.spec: PUSH BC LD C,A AND 192 RRCA RRCA RRCA ;Enter with 'a' holding y line (0-191 LD H,A ;returns with HL holding screen addr LD A,C AND 7 OR H LD H,A LD A,C AND 56 RLCA RLCA LD L,A POP BC RET ;Convert y coord to MODE 2 address... ;------------------------------------ find.y.mode2: LD H,A LD L,0 SRL H RR L SRL H RR L SRL H RR L RET ;Initialise bitmap. ;------------------ ;This section sets up variables... ;as if for a MODE 4 bitmap. mode3 is called if needed to stash ;a MODE 3 bmp set.bmp.mode4: LD DE,&0401 ;D holds no' of bits per pixl ;(4 for mode 4). E holds ;width of image DIV 256... ;1 for mode 4. video.mode: LD A,&00 CP 64 JR NZ,mode4.picture LD DE,&0202 ;Sets to 2 bits per pixel, ;width of image 512 (div 256 ;=2) mode4.picture: LD IX,width LD (IX+0),&00 ;Width is set here LD (IX+1),E LD (IX+2),0 LD (IX+3),0 LD IX,bits ;Bits per pixel- 4 for mode4 LD (IX+0),D ; 2 for mode3 LD (IX+1),0 RET ;Convert SAM palette to 24-bit RGB ;--------------------------------- ;>Uses the following format: ;>R: 765 432 10 G: 765 432 10 B: 765 432 10 ;> R1 R0 H G1 G0 H B1 B0 H ;^ this was the original method. Now uses a full spread. ;Although this may not be perfect, it is pretty accurate. ;Entered with B holding no' of palette colours (4 or 16) ; HL holding start of SAM palette data palette.conv: LD IX,palette.bgr palette.loop: LD A,(HL) CALL decode.pal ;convert from SAM CLUT to RGB LD (IX+0),E LD (IX+1),D LD (IX+2),C LD DE,4 ADD IX,DE INC HL DJNZ palette.loop RET ;Converts raw SAM palette data to 24 bits... ;Enters: A=SAM Palette number ;Exits: C=RED 8bit, D=GRN 8bit, E=BLU 8bit ; SAM PALETTE: 76543210 ; xGRBHgrb decode.pal: PUSH HL PUSH AF bright: AND %00001000 RRCA RRCA RRCA LD C,A LD E,A LD D,A ;BRIGHT=bit 0 of all... POP AF red: BIT 5,A JR Z,not.hired SET 2,C not.hired: BIT 1,A JR Z,blue SET 1,C blue: BIT 4,A JR Z,not.hiblu SET 2,E not.hiblu: BIT 0,A JR Z,green SET 1,E green: BIT 6,A JR Z,not.higrn SET 2,D not.higrn: BIT 2,A JR Z,quantize.rgb SET 1,D quantize.rgb: LD L,C LD H,0 PUSH DE LD DE,quantize.table ADD HL,DE POP DE LD C,(HL) LD L,D LD H,0 PUSH DE LD DE,quantize.table ADD HL,DE POP DE LD D,(HL) LD L,E LD H,0 PUSH DE LD DE,quantize.table ADD HL,DE POP DE LD E,(HL) POP HL RET ;Allow return to SAM basic: ;-------------------------- ret.to.basic: low.page: LD A,&00 OUT (lmpr),A sp.store: LD SP,&0000 EI RET ;*************************************************************** ;Quantized (full spread) separate primary colour value expansion ;tables - expands 8 level brightness to 256 level... quantize.table: DEFB 0,36,73,109,146,182,219,255 ;*************************************************************** ;BMP File header details - partially already filled in. bmp.header: DEFM "BM" ;2 char ID filesize: DEFW 0,0 ;LONG filesize reserved: DEFB 0,0,0,0 ;reserved bytes headersize: DEFW 0,0 ;LONG headersize infosize: DEFW 40,0 ;LONG infosize width: DEFW 256,0 ;LONG width depth: DEFW 192,0 ;LONG depth (192) biplanes: DEFB 1,0 ;INT bitplanes bits: DEFB 4,0 ;INT bits bicompression: DEFW 0,0 ;LONG compression bisizeimage: DEFW 24576,0 ;LONG length of image in byts xpelspermetre: DEFW 0,0 ;LONG X pels per metre ypelspermetre: DEFW 0,0 ;LONG Y pels per metre colourused: DEFW 0,0 ;LONG actual no' colours colourimportnt:DEFW 0,0 ;LONG no' of important colors end.bmp.header:EQU $ ;************ palette.store: DEFS 20 ;Temporary palette store palette.bgr: DEFS 64 ;Temporary RGB palette store ;************ bit.map.buffer: ;converted bitmaps go here... DEFS 16383 DEFS 8193 length: EQU end.bmp.header-start