NAME !gameMTX.ROMS.GAMERom page EQU &FAD2 TYPE rom ; temporary storage, well out of the way of the incomming game ; approx 200 bytes free between stack at &FD4B coming down ; and keyboard buffer &FB4B (160 bytes) sector EQU &FBF0 key EQU &fbf1 lstpg equ &fa7a page equ &fad2 ; 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 ;make sure the CTC iterrupts are off just in case call ctc_off call welcome_beep ;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 code to program vdp as we're loading before the OS has initiallised everything. CALL vdp_setup ;set text display CALL char_map ;make sure we have a readable text screen,with box graphics .key_loop CALL welcome_page call scan call readkey ;returns an index value in A only accepts 0-9 and A-Z CALL cls call get_dir ;returns with HL pointing to the start of the directory ld a,(hl) ld (sector),a ;save the location for later add a,a jr c,key_loop ;loop if empty entry call loading_message ; first sector paged in on exit ; call space ;wait only needed while developing call loadgame ;wont exit unless the game tries to exit to basic (ie reversi) jp boot ;so re-start if it does .welcome_beep ;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 ;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 .get_dir push bc and &3f ld l,a ld h,0 ;multipy index by 16 add hl,hl add hl,hl add hl,hl add hl,hl ld bc,directory add hl,bc pop bc ret .space ; make sure space key up LD A,&7F OUT (5),A IN A,(6) AND 1 JR Z space ; no test for key press .space2 LD A,&7F OUT (5),A IN A,(6) AND 1 JR NZ space2 RET ;catalogue entry in HL .loadgame ld hl,&4000 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 ld a,(sector) add a,a add a,a ;shift bit 6 to carry push de ;push the start address onto the stack jr c,two_part ldir ;since we only have less than 1 page full, copy to ram pop hl jp (hl) ;and jump to the entry point .two_part push bc ;save the file length count ld bc,&3ffc ;remainder of the block (16k- 4 bytes) is all data LDIR ;move the first part ld a,(sector) ;page in the next page inc a and &3f out (&ff),a ld hl,&c004 ;hl is now -&3ffc pop bc ;add the file size add hl,bc ld b,h ld c,l ;BC now holds the balance to load ld hl,&4000 ;which starts at the beginning of the fresh page ldir ;move the 2nd pard pop hl jp (hl) ;jump to start via the save value above ; scan the rom image that is paged in at &4000, paging port is &FF ; &4000 ID byte ; &4001 to &400E is the name, padded out with spaces ; &400F is zero terminator for the print routine ; &4010/1 is the load/run address ; &4012/13 is the size ; &4014 onwards is the file ; if it's a 2 part file, the 2nd part follows on directly at &4000 ; in the next page .scan ld hl,directory ld e,0 ;file counter .scan_loop ld a,(hl) ;get the ID byte inc hl ;point to the name add a,a ;get b7 to carry jr c,scan_done ;we have a valid entry, so work out the screen position ld a,e add a,8 rra ld b,a ;row position A/2 +4 , carry now set if we had an odd number in e ld a,5 ;screen is set up for 14 char names starting in col 5 or 24 jr nc scan1 add a,19 .scan1 ld c,a call print_at ; add 15 to HL, for the next directory entry and increment the screen position ld a,l add a,15 ld l,a ld a,h adc a,0 ld h,a inc e jr scan_loop .scan_done ret .vdp_setup LD B,8 LD C,&80 LD HL,vdp_table .vdp_1 LD A,(HL) OUT (2),A LD A,C OUT (2),A INC C INC HL DJNZ vdp_1 RET .vdp_table DB &00,&D0,&07,&00,&03,&7E,&07,&F4 .char_map LD A,0 OUT (2),A LD A,&59 OUT (2),A LD HL,char_table ld de,&300 .char_loop ld a,(hl) out (1),a inc hl dec DE ld a,E or d jr nz,char_loop RET .cls push af push de LD A,0 OUT (2),A LD A,&5C OUT (2),A LD de,960 .cls_1 LD A,32 OUT (1),A dec de ld a,d or e jr nz,cls_1 pop de pop af RET .welcome_page LD HL,page_text LD A,0 OUT (2),A nop LD A,&5C OUT (2),A ld de,960 .welcome_loop ld a,(hl) out (1),a inc hl dec DE ld a,E or d jr nz,welcome_loop RET .readkey call &0079 ;ready keyboard, jr z,readkey ; char in A or Z set ? cp +ASC"0" jr c,readkey cp +ASC":" jr c,zero_to_nine and +%11011111 ;take care of lower case cp +ASC"A" jr c,readkey cp +ASC"[" jr c,a_to_z jr readkey .a_to_z sub 7 .zero_to_nine sub +asc"0" ld (key),a RET ;on entry HP point to the directory entry .loading_message push bc push hl ld hl,mess ld b,1 ld c,1 call print_at pop hl push hl inc hl ;skip over the location pointer ld c,10 call print_at ;print the name ld a,(sector) and &3f out (&ff),a ;page the rom ld ix,&4000 ;file data will be in &4000 to &4003 ld b,3 ld c,1 ld hl,mess1 call print_at ld l,(ix+0) ld h,(ix+1) call print_hex ;print load address ld b,5 ld hl,mess2 call print_at ld l,(ix+2) ld h,(ix+3) call print_hex ;print size ld c,1 ld b,7 ld hl,mess3 call print_at pop hl pop bc ret .mess dz "Loading:" .mess1 dz "Address:" .mess2 Dz "Length:" .mess3 Dz "< Press Space >" ;"usefull" routines here .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 .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 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 .print_at ;c=across ;b=down ;hl=data ,zero terminated PUSH HL PUSH DE PUSH BC PUSH AF PUSH HL LD L,B LD H,0 PUSH HL ADD HL,HL ;*2 ADD HL,HL ;*4 POP DE ADD HL,DE ;*5 ADD HL,HL ;*10 ADD HL,HL ;*20 ADD HL,HL ;*40 LD B,&5C ADD HL,BC LD A,L OUT (2),A LD A,H OUT (2),A POP HL .print_next LD A,(HL) CP 0 JR Z printed OUT (1),A INC HL JR print_next .printed POP AF POP BC POP DE POP HL RET ;recursive print value in HL as 4 digit hex, direct to screen with out(1) ;as assums screen pointers already set up by the print at routine above .print_hex ld a,h call print_a ld a,l .print_a push af srl a srl a srl a srl a call print_digit pop af .print_digit and &0f add a,&30 cp &3A jr c no_add add a,7 .no_add out (1),a ret .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 ; just static date from here on org &3500 ; first column of screen needs to be empty due to the overscan ;problems on an analog TVs .page_text DS " MTX Rom based Games system V0.05" DS " [~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]" DS " | The Following games were found: |" DS " \~~~~~~~~~~~~~~~~~~{~~~~~~~~~~~~~~~~~~^" DS " | 0 | 1 |" DS " | 2 | 3 |" DS " | 4 | 5 |" DS " | 6 | 7 |" DS " | 8 | 9 |" DS " | A | B |" DS " | C | D |" DS " | E | F |" DS " | G | H |" DS " | I | J |" DS " | K | L |" DS " | M | N |" DS " | O | P |" DS " | Q | R |" DS " | S | T |" DS " | U | V |" DS " | W | X |" DS " | Y | Z |" DS " _~~~~~~~~~~~~~~~~~~}~~~~~~~~~~~~~~~~~~`" DS " Press 0-9 or A-Z to load game " ORG &3900 .char_table DB &00,&00,&00,&00,&00,&00,&00,&00 DB &20,&20,&20,&20,&00,&00,&20,&00 DB &50,&50,&50,&00,&00,&00,&00,&00 DB &50,&50,&F8,&50,&F8,&50,&50,&00 DB &20,&78,&A0,&70,&28,&F0,&20,&00 DB &C8,&C8,&10,&20,&40,&98,&98,&00 DB &40,&A0,&A0,&40,&A8,&90,&68,&00 DB &60,&20,&40,&00,&00,&00,&00,&00 DB &10,&20,&40,&40,&40,&20,&10,&00 DB &40,&20,&10,&10,&10,&20,&40,&00 DB &00,&A8,&70,&F8,&70,&A8,&00,&00 DB &00,&20,&20,&F8,&20,&20,&00,&00 DB &00,&00,&00,&60,&60,&20,&40,&00 DB &00,&00,&00,&F8,&00,&00,&00,&00 DB &00,&00,&00,&00,&60,&60,&00,&00 DB &08,&08,&10,&20,&40,&80,&80,&00 DB &20,&50,&88,&88,&88,&50,&20,&00 DB &20,&60,&20,&20,&20,&20,&70,&00 DB &70,&88,&08,&10,&20,&40,&F8,&00 DB &F8,&10,&20,&10,&08,&88,&70,&00 DB &10,&30,&50,&90,&90,&F8,&10,&00 DB &F8,&80,&F0,&08,&08,&88,&70,&00 DB &70,&80,&80,&F0,&88,&88,&70,&00 DB &F8,&08,&08,&10,&20,&40,&40,&00 DB &70,&88,&88,&70,&88,&88,&70,&00 DB &70,&88,&88,&78,&08,&08,&70,&00 DB &00,&00,&60,&60,&00,&60,&60,&00 DB &00,&60,&60,&00,&60,&60,&20,&40 DB &10,&20,&40,&80,&40,&20,&10,&00 DB &00,&00,&F8,&00,&F8,&00,&00,&00 DB &40,&20,&10,&08,&10,&20,&40,&00 DB &70,&88,&08,&10,&20,&00,&20,&00 DB &70,&88,&B8,&A8,&B8,&80,&78,&00 DB &20,&50,&88,&88,&F8,&88,&88,&00 DB &F0,&88,&88,&F0,&88,&88,&F0,&00 DB &70,&88,&80,&80,&80,&88,&70,&00 DB &F0,&88,&88,&88,&88,&88,&F0,&00 DB &F8,&80,&80,&F0,&80,&80,&F8,&00 DB &F8,&80,&80,&F0,&80,&80,&80,&00 DB &70,&88,&80,&B8,&88,&88,&70,&00 DB &88,&88,&88,&F8,&88,&88,&88,&00 DB &70,&20,&20,&20,&20,&20,&70,&00 DB &78,&10,&10,&10,&90,&90,&60,&00 DB &88,&90,&A0,&C0,&A0,&90,&88,&00 DB &80,&80,&80,&80,&80,&80,&F8,&00 DB &88,&D8,&A8,&A8,&88,&88,&88,&00 DB &88,&88,&C8,&A8,&98,&88,&88,&00 DB &70,&88,&88,&88,&88,&88,&70,&00 DB &F0,&88,&88,&F0,&80,&80,&80,&00 DB &70,&88,&88,&88,&A8,&90,&68,&00 DB &F0,&88,&88,&F0,&A0,&90,&88,&00 DB &70,&88,&80,&70,&08,&88,&70,&00 DB &F8,&20,&20,&20,&20,&20,&20,&00 DB &88,&88,&88,&88,&88,&88,&70,&00 DB &88,&88,&88,&88,&50,&50,&20,&00 DB &88,&88,&88,&A8,&A8,&A8,&50,&00 DB &88,&88,&50,&20,&50,&88,&88,&00 DB &88,&88,&50,&20,&20,&20,&20,&00 DB &F8,&08,&10,&20,&40,&80,&F8,&00 DB &00,&00,&7C,&40,&40,&4C,&48,&48 DB &48,&48,&4c,&40,&40,&4c,&48,&48 DB &00,&00,&f8,&08,&08,&c8,&48,&48 DB &48,&48,&c8,&08,&08,&c8,&48,&48 DB &48,&48,&4c,&40,&40,&7c,&00,&00 DB &48,&48,&c8,&08,&08,&f8,&00,&00 DB &00,&00,&60,&10,&70,&90,&78,&00 DB &80,&80,&E0,&90,&90,&90,&E0,&00 DB &00,&00,&70,&80,&80,&80,&70,&00 DB &10,&10,&70,&90,&90,&90,&78,&00 DB &00,&00,&70,&88,&F8,&80,&78,&00 DB &30,&40,&40,&E0,&40,&40,&40,&00 DB &00,&00,&78,&88,&78,&08,&88,&70 DB &80,&80,&E0,&90,&90,&90,&90,&00 DB &20,&00,&60,&20,&20,&20,&70,&00 DB &20,&00,&60,&20,&20,&20,&20,&C0 DB &80,&80,&90,&A0,&C0,&A0,&90,&00 DB &60,&20,&20,&20,&20,&20,&70,&00 DB &00,&00,&50,&A8,&A8,&A8,&A8,&00 DB &00,&00,&E0,&90,&90,&90,&90,&00 DB &00,&00,&70,&88,&88,&88,&70,&00 DB &00,&00,&E0,&90,&90,&E0,&80,&80 DB &00,&00,&38,&48,&48,&38,&08,&08 DB &00,&00,&B0,&C0,&80,&80,&80,&00 DB &00,&00,&70,&80,&70,&08,&F0,&00 DB &40,&40,&F0,&40,&40,&40,&30,&00 DB &00,&00,&90,&90,&90,&90,&68,&00 DB &00,&00,&88,&88,&50,&20,&20,&00 DB &00,&00,&88,&88,&A8,&A8,&50,&00 DB &00,&00,&88,&50,&20,&50,&88,&00 DB &00,&00,&48,&48,&48,&38,&08,&70 DB &00,&00,&F8,&10,&20,&40,&F8,&00 DB &00,&00,&FC,&00,&00,&CC,&48,&48 DB &48,&48,&48,&48,&48,&48,&48,&48 DB &48,&48,&CC,&00,&00,&FC,&00,&00 DB &00,&00,&FC,&00,&00,&FC,&00,&00 DB &F8,&F8,&F8,&F8,&F8,&F8,&F8,&F8 .directory ;dieectory added in by the rom builder program ;space for 63, 16 byte entries, 64 is always end of table/empty ;NB the menu currently only has room for 36 entries ;Format ;ID byte 6 bits file locator, b6 is block size, b7 set for end of table/empty entry. ;14 bytes of name ;0 byte name terminator