NAME !gameMTX.ROMS.GraphicRom100 TYPE rom ;Change History ; Version 1.00 release version, cosmetic changes from 0.22 only ; Version 0.22 I/O port changed to &FB to batch hardware revision 5.1 ; version 0.21 Spacebar check added on startup. ; Version 0.20 CTC changes rolled back to V0.18 due to causing crashes ; Version 0.19 CTC and other setup changes ; Version 0.16 Keybaord range extended for up to 38 games ; Version 0.15 Garpics 2 mode used, redundant code deleted. ; temporary storage, well out of the way of the incomming game ; in approx 200 bytes free between stack at &FD48 coming down ; and keyboard buffer &FB4B sector EQU &FBF0 key EQU &fbf1 port EQU &FB lstpg equ &fa7a sstack equ &fa96 page equ &fad2 setcall EQU &fd48 ; Code starts at &2000, as only the upper half of the 16k rom space is paged. ORG &2000 ;if bytes 0 - 7 are 8-1 resp. autoboot rom via &2010 on power up/reset ;but after high memory cleared, any variables set will be retained DB 8 DB 7 DB 6 DB 5 DB 4 DB 3 DB 2 DB 1 ; BASIC's ROM command enters at &200C ORG &200C JP run DB 0 ;boot entry point &2010 JP boot ; Skeleton for the rom X entry point routine ;not used here, kept in place for completeness. .run PUSH HL PUSH DE PUSH BC PUSH AF PUSH IX PUSH IY ;code goes here POP IY POP IX POP AF POP BC POP DE ;tidy the stack on exit LD L,&00 EX (SP),HL JP &0089 .boot ; first test for space pressed ; can exit via a return as the startup code ; is entered via a call. LD A,&7F OUT (5),A IN A,(6) AND 1 ret NZ ;setup the stack ld hl,setcall ld (sstack),hl ld sp,(sstack) ;the sound chip seems to default to making a noise at startup, ; and we're loading before the OS kills the volume ;so kill all 4 channels call sound_off ;this is the MTX VDINIT routine, which is run immediately after the autostart rom check. rst &28 db &42 ;select and clear VS 4 using RST 10 functions, which now work, thanks to VDinit rst &10 db &4C ;set the border to black LD a,&F1 out (2),a ld a,&87 out (2),a ;make sure the CTC iterrupts are off just in case call ctc_off ;make sure we're in the correct page (0 for 32k, 1 for 64k, 3 for 128k ;or the data rom wont be acessible ld a,(lstpg) or &70 ld (page),a out (0),a CALL welcome_page call welcome_beep .key_loop call readkey ;returns an index value in A only accepts 0-9 and A-Z and &3f LD HL,directory add a,l ld l,a ld a,(hl) ld (sector),a ;save the location for later inc a jr z,key_loop ;loop if empty entry call loadgame ;wont exit unless the game tries to exit to basic (ie reversi) jp boot ;so re-start if it does .welcome_beep ;now make the hello! beep ld hl,20000 call beep_hl ld hl,0 call delay call sound_off ld hl,20000 call delay ld hl,28000 call beep_hl ld hl,30000 call delay call sound_off ret ;catalogue entry in HL .loadgame call find_sector ld e,(hl) inc hl ld d,(hl) ;DE now holds the loading address inc hl ld c,(hl) inc hl ld b,(hl) ;BC now has the file size inc hl ;HL now points to the first byte which is also the codes entry point push de ;push the start address onto the stack push BC ;save the file size ld BC,&7fc ;first sector is 4 bytes short because of the header LDIR ;transfer the short sector, no file size check as all entrys must be ;at least one sector ld bc,&f804 ;-&7fC .block_loop pop hl ;get the remaining file size add hl,bc ret nc ;if Carry isn't set then there were less than &800 (7FC) bytes left ;so exit via run address stacked above push hl ;re-stack the remaining file size ld bc,&800 ;and set BC for a full sector transfer ld a,(sector) inc a ld (sector),a call find_sector ldir ;transfer 1 sector full, DE ld bc,&f800 ;set BC to -&800 for 2nd and later sectors jr block_loop ;Screem character map for graphics mode is stored at &0000, ;the colour data is stored at &2000, both tables are &1800 bytes long ;bit 6 of 2nd transfer set to indicate writing to Vram ;the screen data is compressed, &FF isn't used anywhere in the ;screen builder so is the flag for compression ;&FF,byte,count, for a compressed chunk ;&FF,FF is the end of table marker, but the byte count should stop ;the transfer immediatly before them. .welcome_page push af push de push hl LD HL,screendata LD de,&1800 ld BC &4000 call decomp LD HL,colourdata LD de,&1800 ld BC &6000 call decomp pop hl pop de pop bc ret .decomp LD A,c OUT (2),A LD A,b OUT (2),A .decomp_loop ld a,(hl) inc hl ;check for compression marker cmp &ff jr z,compressed out (1),a dec de ld a,d or e jr nz,decomp_loop ret .compressed ;get the data byte ld c,(hl) inc hl ;get the count ld b,(hl) inc hl .comp_loop ld a,c out (1),a dec de ;check to see if we're end of the bitmap ld a,d or e ret z DJNZ comp_loop jr decomp_loop ;MTX's main keyboard routine is at &0079, and returns Z set if no key ;or the ASCII code in A .readkey call &0079 ;read keyboard, jr z,readkey ;wait for something to be pressed cp +ASC"0" jr c,readkey cp +ASC":" jr c,zero_to_nine and +%11011111 ;take care of lower case cp +ASC"@" jr c,readkey cp +ASC"\" jr c,a_to_z_ish jr readkey .a_to_z_ish sub 6 .zero_to_nine sub +asc"0" ld (key),a RET ;"usefull" routines here ;return HL pointing to the start of a 2k secotor, with the relevant ;chunk paged in .find_sector push af ld a,(sector) ; sectors are 2k, banked pages 16k, so divide by 8 RRCA RRCA RRCA and &1f out (port),a ;page the rom ld a,(sector) ;now work out where the load data is on the page and &07 ;intra page offset, needs multiplying by 2k add a,a add a,a add a,a add a,&40 ;page offset in memory ld h,a ld l,0 pop af ret ;generic intrrupt cancelling routine. .ctc_off push bc push af ld b,2 .ctc_loop ld a,3 out (&8),a out (&9),a out (&a),a out (&b),a djnz ctc_loop pop af pop bc ret ; set all 4 sound channels to silence, using the data table that follows .sound_off PUSH AF PUSH BC push hl Ld hl,sound_data ld b,12 .sound_loop ld a,(hl) OUT (6),A IN A,(3) nop ; at least 32 cycles needed between accesses nop ; 8 nops used to ensure the requirement is met nop nop nop nop nop nop inc hl DJNZ sound_loop pop hl pop bc pop af ret .sound_data db &80,00 ;Channel 0, frequency 0 db &9f ;channel 0, attenuation off db &A0,00 ;Channel 1, frequency 0 db &Bf ;channel 1, attenuation off db &C0,00 ;Channel 2, frequency 0 db &Df ;channel 2, attenuation off db &Ff ;channel 3, attenuation off db &E0,00 ;Channel 3, periodic noise N/512 .delay PUSH HL PUSH BC .delay_loop DEC HL LD A,H OR L JR NZ,delay_loop POP BC POP HL RET .beep_hl push AF push BC LD A,L AND &0F OR &80 OUT (6),A ; SEND TONE 1 + 4 BITS OF FREQUENCY NOP IN A,(3) LD A,L SRL A SRL A SRL A SRL A LD C,A LD A,H SLA A SLA A SLA A SLA A OR C AND &3F ; REMAINING 10 BITS OF FREQUENCY OUT (6),A NOP IN A,(3) LD A,&90 ; ATTENUATION 0DB TONE 1 NOP NOP NOP NOP OUT (6),A NOP IN A,(3) pop bc pop AF RET ORG &2280 .Screendata ; compressed screenimage placed here by the builder ORG &3180 .colourdata ORG &3FC0 .directory ;list of starting sector for each game ;&FF should be present in the first unused entry