• R/O
  • SSH
  • HTTPS

oricsdk: Commit


Commit MetaInfo

Revision1578 (tree)
Time2022-03-06 00:06:09
Authordbug

Log Message

Improved Hobbit v1.5

NOTE: Ideally I'd like to do more fixes, so please avoid distributing it all over the place.
NOTE2: If this is not finished after one year, feel free to ignore the note above, it just means that "life happened" and this version is better than a non existing better one.

Version historic:
- 1.0 - 2015-04-13 [Silicebit] First DSK version of the Hobbit (see: https://forum.defence-force.org/viewtopic.php?f=20&t=1225)

Note that attempting to use the SAVE or LOAD commands will still try to use the original tape code.

- 1.1 - 2015-04-14 [Silicebit] Same version, buyt with a INIST so the game autostarts
- 1.2 - 2022-02-23 [Dbug] Added this code that patches the game to speed-up the drawing routines using some multiplication, divide and modulo tables
- 1.3 - 2022-02-24 [Dbug] Replaced the system font by a fancy one ("oncial") to make the game feel a bit more atmospheric
- 1.4 - 2022-02-25 [Dbug] Added an intro picture based on the original game manual artwork
- 1.5 - 2022-02-26 [Dbug] The intro picture now appears with an unroll effect, and a music play in the background

TODO list:
- Modify the SAVE and LOAD code to use the floppy disk instead of tape
- Add proper credits to the game
- Add a way to show a manual directly on the game

Information regarding the game:
- HOBBIT.COM is 36176 bytes and loads/runs from $4fe
- There is code at $91B2 which recreates the $400-$4FF area which interfered with the Sedoric code in page 4
- $7422 contains the location of the routine that computes the screen address of a specific pixel
- The $405-$414 area contains a JMP table on various ROM routines patched to different addresses depending if an Oric 1 or Atmos is detected (See: https://forum.defence-force.org/viewtopic.php?p=26656#p26656)
- The saving code is called multiple time for various areas, totally about 3623 bytes (see: https://forum.defence-force.org/viewtopic.php?p=26664#p26664)

Change Summary

Incremental Difference

--- users/dbug/UpgradeTime/TheHobbit/intro.s (nonexistent)
+++ users/dbug/UpgradeTime/TheHobbit/intro.s (revision 1578)
@@ -0,0 +1,992 @@
1+;
2+; This intro is still heavy work in progress, with bits of code ripped out from "MymPlayer" and "Pushing The Enveloppe"
3+;
4+#define VIA_1 $30f
5+#define VIA_2 $30c
6+
7+#define BASIC_KEY $2df ; Latest key from keyboard, bit 7 set if valid
8+
9+#define PLAY_MUSIC
10+
11+ .zero
12+
13+ *= $50
14+
15+tmp0 .dsb 2
16+tmp1 .dsb 2
17+
18+pos_y .dsb 1
19+
20+_DecodedByte .dsb 1 ; Byte being currently decoded from the MYM stream
21+_DecodeBitCounter .dsb 1 ; Number of bits we can read in the current byte
22+_DecodedResult .dsb 1 ; What is returned by the 'read bits' function
23+
24+_CurrentAYRegister .dsb 1 ; Contains the number of the register being decoded
25+
26+_RegisterBufferHigh .dsb 1 ; Points to the high byte of the decoded register buffer, increment to move to the next register
27+_BufferFrameOffset .dsb 1 ; From 0 to 127, used when filling the decoded register buffer
28+
29+_MusicResetCounter .dsb 2 ; Contains the number of rows to play before reseting
30+
31+_CurrentFrame .dsb 1 ; From 0 to 255 and then cycles... the index of the frame to play this vbl
32+
33+_PlayerVbl .dsb 1
34+_MusicLooped .dsb 1
35+
36+_FrameLoadBalancer .dsb 1 ; We depack a new frame every 9 VBLs, this way the 14 registers are evenly depacked over 128 frames
37+
38+ .text
39+
40+ *= $600
41+
42+_Main
43+.(
44+ jsr StartMusic
45+ jsr SwitchToHires
46+ jsr _InitTransitionData
47+ jsr StartPictureUnroll
48+loop
49+ jsr _VSync
50+ jsr PictureUnrollFrame
51+ jsr _VSync
52+
53+ lda BASIC_KEY ; Key
54+ bpl loop
55+
56+ jsr SwitchToText
57+ jsr EndMusic
58+ rts
59+.)
60+
61+
62+ClearVideo
63+ ;jmp SwitchToHires
64+.(
65+ ; Clean the entire screen area from $A000 to $BFFF with zeroes (BLACK INK attribute)
66+ lda #<$a000
67+ sta tmp0+0
68+ lda #>$a000
69+ sta tmp0+1
70+
71+ lda #0
72+ ldx #32
73+next_page
74+ tay
75+clear_page
76+ sta (tmp0),y
77+ dey
78+ bne clear_page
79+
80+ inc tmp0+1
81+ dex
82+ bne next_page
83+ rts
84+.)
85+
86+
87+SwitchToHires
88+.(
89+ ; Clean the entire screen area from $A000 to $BFFF with zeroes (BLACK INK attribute)
90+ jsr ClearVideo
91+
92+ ; Put the HIRES attribute at the bottom, and wait one frame
93+ lda #30
94+ sta $bfdf
95+
96+ jmp _VSync
97+.)
98+
99+SwitchToText
100+.(
101+ ; Clean the entire screen area from $A000 to $BFFF with zeroes (BLACK INK attribute)
102+ jsr ClearVideo
103+
104+ ; Put the HIRES attribute at the bottom, and wait one frame
105+ lda #26
106+ sta $bfdf
107+
108+ jmp _VSync
109+.)
110+
111+
112+; 16 entries
113+MiniTableUnroll
114+ .byt 0 ; The normal line of the picture
115+ .byt 255 ; A black line for special effect
116+ .byt 32
117+ .byt 29
118+ .byt 27
119+ .byt 26
120+ .byt 25
121+ .byt 24
122+ .byt 23
123+ .byt 22
124+ .byt 21
125+ .byt 20
126+ .byt 19
127+ .byt 17
128+ .byt 14
129+ .byt 10
130+ .byt 255 ; A black line for special effect
131+
132+StartPictureUnroll
133+.(
134+ ldy #238
135+ sty pos_y
136+ rts
137+.)
138+
139+
140+PictureUnrollFrame
141+.(
142+ ldy pos_y
143+ cpy #216
144+ bne do_frame
145+ rts
146+
147+do_frame
148+ ldx #0
149+loop_roll
150+ lda MiniTableUnroll,x
151+ bmi no_wrap
152+ clc
153+ adc pos_y
154+no_wrap
155+ tay
156+
157+ lda _PictureLoadBufferAddrLow,y
158+ sta tmp0+0
159+ lda _PictureLoadBufferAddrHigh,y
160+ sta tmp0+1
161+
162+ clc
163+ txa
164+ adc pos_y
165+ tay
166+
167+ lda _ScreenAddrLow,y
168+ sta tmp1+0
169+ lda _ScreenAddrHigh,y
170+ sta tmp1+1
171+
172+ ; Copy from right to left to limit the attribute corruption effects
173+ ldy #40
174+loop
175+ lda (tmp0),y
176+ sta (tmp1),y
177+ dey
178+ bne loop
179+
180+ inx
181+ cpx #16
182+ bne loop_roll
183+
184+ inc pos_y
185+ rts
186+.)
187+
188+
189+
190+_InitTransitionData
191+.(
192+ lda #<_TitlePicture-1
193+ sta tmp0+0
194+ lda #>_TitlePicture-1
195+ sta tmp0+1
196+
197+ lda #<$a000-1
198+ sta tmp1+0
199+ lda #>$a000-1
200+ sta tmp1+1
201+
202+ .(
203+ ldx #0
204+loop
205+ clc
206+ lda tmp0+0
207+ sta _PictureLoadBufferAddrLow,x
208+ adc #40
209+ sta tmp0+0
210+ lda tmp0+1
211+ sta _PictureLoadBufferAddrHigh,x
212+ adc #0
213+ sta tmp0+1
214+
215+ clc
216+ lda tmp1+0
217+ sta _ScreenAddrLow,x
218+ adc #40
219+ sta tmp1+0
220+ lda tmp1+1
221+ sta _ScreenAddrHigh,x
222+ adc #0
223+ sta tmp1+1
224+
225+ inx
226+ cpx #200
227+ bne loop
228+ .)
229+
230+ .(
231+loop
232+ lda #<_EmptySourceScanLine
233+ sta _PictureLoadBufferAddrLow,x
234+ lda #>_EmptySourceScanLine
235+ sta _PictureLoadBufferAddrHigh,x
236+
237+ lda #<_EmptyDestinationScanLine
238+ sta _ScreenAddrLow,x
239+ lda #>_EmptyDestinationScanLine
240+ sta _ScreenAddrHigh,x
241+
242+ inx
243+ bne loop
244+ .)
245+
246+ rts
247+.)
248+
249+
250+DisplayPicture
251+.(
252+ lda #<_TitlePicture
253+ sta tmp0+0
254+ lda #>_TitlePicture
255+ sta tmp0+1
256+
257+ lda #<$a000
258+ sta tmp1+0
259+ lda #>$a000
260+ sta tmp1+1
261+
262+ ldx #200
263+loop_y
264+ ldy #39
265+loop_x
266+ lda (tmp0),y
267+ sta (tmp1),y
268+ dey
269+ bpl loop_x
270+
271+ clc
272+ lda tmp0+0
273+ adc #40
274+ sta tmp0+0
275+ lda tmp0+1
276+ adc #0
277+ sta tmp0+1
278+
279+ clc
280+ lda tmp1+0
281+ adc #40
282+ sta tmp1+0
283+ lda tmp1+1
284+ adc #0
285+ sta tmp1+1
286+
287+ dex
288+ bne loop_y
289+
290+ rts
291+.)
292+
293+
294+
295+StartMusic
296+ php
297+ pha
298+ sei
299+
300+ clc
301+ lda $fffe
302+ adc #1
303+ sta __auto_1+1
304+ sta __auto_3+1
305+ sta __auto_5+1
306+ lda $ffff
307+ adc #0
308+ sta __auto_1+2
309+ sta __auto_3+2
310+ sta __auto_5+2
311+
312+ clc
313+ lda $fffe
314+ adc #2
315+ sta __auto_2+1
316+ sta __auto_4+1
317+ sta __auto_6+1
318+ lda $ffff
319+ adc #0
320+ sta __auto_2+2
321+ sta __auto_4+2
322+ sta __auto_6+2
323+
324+ ; Save the old handler value
325+__auto_1
326+ lda $245
327+ sta jmp_old_handler+1
328+__auto_2
329+ lda $246
330+ sta jmp_old_handler+2
331+
332+ ; Install our own handler
333+ lda #<irq_handler
334+__auto_3
335+ sta $245
336+ lda #>irq_handler
337+__auto_4
338+ sta $246
339+
340+ jsr _Mym_Initialize
341+
342+ pla
343+ plp
344+ rts
345+
346+
347+EndMusic
348+ php
349+ pha
350+ sei
351+
352+ ; Restore the old handler value
353+ lda jmp_old_handler+1
354+__auto_5
355+ sta $245
356+ lda jmp_old_handler+2
357+__auto_6
358+ sta $246
359+
360+ ; Stop the sound
361+ lda #8
362+ ldx #0
363+ jsr WriteRegister
364+
365+ lda #9
366+ ldx #0
367+ jsr WriteRegister
368+
369+ lda #10
370+ ldx #0
371+ jsr WriteRegister
372+
373+ pla
374+ plp
375+ rts
376+
377+
378+_50hzFlipFlop .byt 0
379+_VblCounter .byt 0
380+
381+irq_handler
382+ pha
383+ txa
384+ pha
385+ tya
386+ pha
387+
388+ ; This handler runs at 100hz if comming from the BASIC,
389+ ; but the music should play at 50hz, so we need to call the playing code
390+ ; only every second frame
391+ lda _50hzFlipFlop
392+ eor #1
393+ sta _50hzFlipFlop
394+ beq skipFrame
395+
396+#ifdef PLAY_MUSIC
397+ jsr _Mym_PlayFrame
398+#endif
399+ inc _VblCounter
400+
401+skipFrame
402+
403+ pla
404+ tay
405+ pla
406+ tax
407+ pla
408+
409+jmp_old_handler
410+ jmp 0000
411+
412+
413+_VSync
414+ lda _VblCounter
415+ beq _VSync
416+ lda #0
417+ sta _VblCounter
418+_DoNothing
419+ rts
420+
421+; http://www.defence-force.org/ftp/oric/documentation/v1.1_rom_disassembly.pdf
422+;
423+; Oric Atmos ROM function W8912
424+; Originally called with JSR F590
425+; F590 08 PHP WRITE X TO REGISTER A 0F 8912.
426+; F591 78 SEI
427+; F592 8D 0F 03 STA $030F Send A to port A of 6522.
428+; F595 A8 TAY
429+; F596 8A TXA
430+; F597 C0 07 CPY #$07 If writing to register 7, set
431+; F599 D0 02 BNE $F59D 1/0 port to output.
432+; F59B 09 40 ORA #$40
433+; F59D 48 PHA
434+; F59E AD 0C 03 LDA $030C Set CA2 (BC1 of 8912) to 1,
435+; F5A1 09 EE ORA #$EE set CB2 (BDIR of 8912) to 1.
436+; F5A3 8D 0C 03 STA $030C 8912 latches the address.
437+; F5A6 29 11 AND #$11 Set CA2 and CB2 to 0, BC1 and
438+; F5A8 09 CC ORA #$CC BDIR in inactive state.
439+; F5AA 8D 0C 03 STA $030C
440+; F5AD AA TAX
441+; F5AE 68 PLA
442+; F5AF 8D 0F 03 STA $030F Send data to 8912 register.
443+; F5B2 8A TXA
444+; F5B3 09 EC ORA #$EC Set CA2 to 0 and CB2 to 1,
445+; F5B5 8D 0C 03 STA $030C 8912 latches data.
446+; F5B8 29 11 AND #$11 Set CA2 and CB2 to 0, BC1 and
447+; F5BA 09 CC ORA #$CC BDIR in inactive state.
448+; F5BC 8D 0C 03 STA $030C
449+; F5BF 28 PLP
450+; F5C0 60 RTS
451+
452+WriteRegister
453+.(
454+ PHP ; WRITE X TO REGISTER A 0F 8912.
455+ SEI
456+ STA $030F ; Send A to port A of 6522.
457+ TAY
458+ TXA
459+ CPY #$07 ; If writing to register 7, set
460+ BNE skip ; 1/0 port to output.
461+ ORA #$40
462+skip
463+ PHA
464+ LDA $030C ; Set CA2 (BC1 of 8912) to 1,
465+ ORA #$EE ; set CB2 (BDIR of 8912) to 1.
466+ STA $030C ; 8912 latches the address.
467+ AND #$11 ; Set CA2 and CB2 to 0, BC1 and
468+ ORA #$CC ; BDIR in inactive state.
469+ STA $030C
470+ TAX
471+ PLA
472+ STA $030F ; Send data to 8912 register.
473+ TXA
474+ ORA #$EC ; Set CA2 to 0 and CB2 to 1,
475+ STA $030C ; 8912 latches data.
476+ AND #$11 ; Set CA2 and CB2 to 0, BC1 and
477+ ORA #$CC ; BDIR in inactive state.
478+ STA $030C
479+ PLP
480+ RTS
481+.)
482+
483+
484+
485+_PlayerCount .byt 0
486+
487+
488+;
489+; Current PSG values during unpacking
490+;
491+_PlayerRegValues
492+_RegisterChanAFrequency
493+ ; Chanel A Frequency
494+ .byt 8
495+ .byt 4
496+
497+_RegisterChanBFrequency
498+ ; Chanel B Frequency
499+ .byt 8
500+ .byt 4
501+
502+_RegisterChanCFrequency
503+ ; Chanel C Frequency
504+ .byt 8
505+ .byt 4
506+
507+_RegisterChanNoiseFrequency
508+ ; Chanel sound generator
509+ .byt 5
510+
511+ ; select
512+ .byt 8
513+
514+ ; Volume A,B,C
515+_RegisterChanAVolume
516+ .byt 5
517+_RegisterChanBVolume
518+ .byt 5
519+_RegisterChanCVolume
520+ .byt 5
521+
522+ ; Wave period
523+ .byt 8
524+ .byt 8
525+
526+ ; Wave form
527+ .byt 8
528+
529+_PlayerRegCurrentValue .byt 0
530+
531+
532+_Mym_ReInitialize
533+.(
534+ sei
535+ lda #0
536+ sta _MusicLooped
537+ jsr _Mym_Initialize
538+ cli
539+ rts
540+.)
541+
542+_Mym_Initialize
543+.(
544+ ; The two first bytes of the MYM music is the number of rows in the music
545+ ; We decrement that at each frame, and when we reach zero, time to start again.
546+ ldx _MusicData+0
547+ stx _MusicResetCounter+0
548+ ldx _MusicData+1
549+ inx
550+ stx _MusicResetCounter+1
551+
552+ .(
553+ ; Initialize the read bit counter
554+ lda #<(_MusicData+2)
555+ sta __auto_music_ptr+1
556+ lda #>(_MusicData+2)
557+ sta __auto_music_ptr+2
558+
559+ lda #1
560+ sta _DecodeBitCounter
561+
562+ ; Clear all data
563+ lda #0
564+ sta _DecodedResult
565+ sta _DecodedByte
566+ sta _PlayerVbl
567+ sta _PlayerRegCurrentValue
568+ sta _BufferFrameOffset
569+ sta _PlayerCount
570+ sta _CurrentAYRegister
571+ sta _CurrentFrame
572+
573+ ldx #14
574+loop_init
575+ dex
576+ sta _PlayerRegValues,x
577+ bne loop_init
578+ .)
579+
580+ ;
581+ ; Unpack the 128 first register frames
582+ ;
583+ .(
584+ lda #>_PlayerBuffer
585+ sta _RegisterBufferHigh
586+
587+ ldx #0
588+unpack_block_loop
589+ stx _CurrentAYRegister
590+
591+ ; Unpack that register
592+ jsr _PlayerUnpackRegister2
593+
594+ ; Next register
595+ ldx _CurrentAYRegister
596+ inx
597+ cpx #14
598+ bne unpack_block_loop
599+ .)
600+
601+ lda #128
602+ sta _PlayerVbl+0
603+
604+ lda #0
605+ sta _PlayerCount
606+ sta _CurrentAYRegister
607+ sta _CurrentFrame
608+
609+ lda #9
610+ sta _FrameLoadBalancer
611+ rts
612+.)
613+
614+
615+
616+_Mym_PlayFrame
617+.(
618+ ;
619+ ; Check for end of music
620+ ; CountZero: $81,$0d
621+ dec _MusicResetCounter+0
622+ bne music_contines
623+ dec _MusicResetCounter+1
624+ bne music_contines
625+music_resets
626+ lda #1
627+ sta _MusicLooped
628+ jsr _Mym_Initialize
629+
630+music_contines
631+
632+ ;
633+ ; Play a frame of 14 registers
634+ ;
635+ .(
636+ lda _CurrentFrame
637+ sta _auto_psg_play_read+1
638+ lda #>_PlayerBuffer
639+ sta _auto_psg_play_read+2
640+
641+ ldy #0
642+register_loop
643+
644+_auto_psg_play_read
645+ ldx _PlayerBuffer
646+
647+ ; W8912
648+ ; jsr $f590
649+ ; a=register
650+ ; x=value
651+ pha
652+ tya
653+ pha
654+ jsr WriteRegister
655+ pla
656+ tay
657+ pla
658+
659+ inc _auto_psg_play_read+2
660+ iny
661+ cpy #14
662+ bne register_loop
663+ .)
664+
665+
666+ inc _CurrentFrame
667+ inc _PlayerCount
668+
669+ lda _CurrentAYRegister
670+ cmp #14
671+ bcs end_reg
672+
673+ .(
674+ dec _FrameLoadBalancer
675+ bne end
676+
677+ jsr _PlayerUnpackRegister
678+ inc _CurrentAYRegister
679+ lda #9
680+ sta _FrameLoadBalancer
681+end
682+ rts
683+ .)
684+
685+end_reg
686+ .(
687+ lda _PlayerCount
688+ cmp #128
689+ bcc skip
690+
691+ lda #0
692+ sta _CurrentAYRegister
693+ sta _PlayerCount
694+ lda #9
695+ sta _FrameLoadBalancer
696+
697+ clc
698+ lda _PlayerVbl+0
699+ adc #128
700+ sta _PlayerVbl+0
701+skip
702+ .)
703+
704+ rts
705+.)
706+
707+
708+
709+
710+;
711+; Initialise X with the number of bits to read
712+; Y is not modifier
713+; A is saved and restored..
714+;
715+_ReadBits
716+ pha
717+
718+ lda #0
719+ sta _DecodedResult
720+
721+ ; Will iterate X times (number of bits to read)
722+loop_read_bits
723+
724+ dec _DecodeBitCounter
725+ bne end_reload
726+
727+ ; reset mask
728+ lda #8
729+ sta _DecodeBitCounter
730+
731+ ; fetch a new byte, and increment the adress.
732+__auto_music_ptr
733+ lda _MusicData+2
734+ sta _DecodedByte
735+
736+ inc __auto_music_ptr+1
737+ bne end_reload
738+ inc __auto_music_ptr+2
739+end_reload
740+
741+ asl _DecodedByte
742+ rol _DecodedResult
743+
744+ dex
745+ bne loop_read_bits
746+
747+ pla
748+ rts
749+
750+
751+
752+
753+
754+_PlayerUnpackRegister
755+ lda #>_PlayerBuffer
756+ clc
757+ adc _CurrentAYRegister
758+ sta _RegisterBufferHigh
759+_PlayerUnpackRegister2
760+ ;
761+ ; Init register bit count and current value
762+ ;
763+ ldx _CurrentAYRegister
764+ lda _PlayerRegValues,x
765+ sta _PlayerRegCurrentValue
766+
767+
768+ ;
769+ ; Check if it's packed or not
770+ ; and call adequate routine...
771+ ;
772+ ldx #1
773+ jsr _ReadBits
774+ ldx _DecodedResult
775+ bne DecompressFragment
776+
777+
778+UnchangedFragment
779+.(
780+ ;
781+ ; No change at all, just repeat '_PlayerRegCurrentValue' 128 times
782+ ;
783+ lda _RegisterBufferHigh ; highpart of buffer adress + register number
784+ sta __auto_copy_unchanged_write+2
785+
786+ ldx #128 ; 128 iterations
787+ lda _PlayerRegCurrentValue ; Value to write
788+
789+ ldy _PlayerVbl
790+
791+repeat_loop
792+__auto_copy_unchanged_write
793+ sta _PlayerBuffer,y
794+ iny
795+ dex
796+ bne repeat_loop
797+.)
798+
799+ jmp player_main_return
800+
801+
802+player_main_return
803+ ; Write back register current value
804+ ldx _CurrentAYRegister
805+ lda _PlayerRegCurrentValue
806+ sta _PlayerRegValues,x
807+
808+ ; Move to the next register buffer
809+ inc _RegisterBufferHigh
810+ rts
811+
812+
813+
814+
815+DecompressFragment
816+ lda _PlayerVbl ; Either 0 or 128 at this point else we have a problem...
817+ sta _BufferFrameOffset
818+
819+decompressFragmentLoop
820+
821+player_copy_packed_loop
822+ ; Check packing method
823+ ldx #1
824+ jsr _ReadBits
825+
826+ ldx _DecodedResult
827+ bne PlayerNotCopyLast
828+
829+UnchangedRegister
830+.(
831+ ; We just copy the current value 128 times
832+ lda _RegisterBufferHigh ; highpart of buffer adress + register number
833+ sta player_copy_last+2
834+
835+ ldx _BufferFrameOffset ; Value between 00 and 7f
836+ lda _PlayerRegCurrentValue ; Value to copy
837+player_copy_last
838+ sta _PlayerBuffer,x
839+
840+ inc _BufferFrameOffset
841+.)
842+
843+
844+player_return
845+
846+ ; Check end of loop
847+ lda _BufferFrameOffset
848+ and #127
849+ bne decompressFragmentLoop
850+
851+ jmp player_main_return
852+
853+
854+PlayerNotCopyLast
855+ ; Check packing method
856+ ldx #1
857+ jsr _ReadBits
858+
859+ ldx _DecodedResult
860+ beq DecompressWithOffset
861+
862+ReadNewRegisterValue
863+ ; Read new register value (variable bit count)
864+ ldx _CurrentAYRegister
865+ lda _PlayerRegBits,x
866+ tax
867+ jsr _ReadBits
868+ ldx _DecodedResult
869+ stx _PlayerRegCurrentValue
870+
871+ ; Copy to stream
872+ lda _RegisterBufferHigh ; highpart of buffer adress + register number
873+ sta player_read_new+2
874+
875+ ldx _BufferFrameOffset ; Value between 00 and 7f
876+ lda _PlayerRegCurrentValue ; New value to write
877+player_read_new
878+ sta _PlayerBuffer,x
879+
880+ inc _BufferFrameOffset
881+ jmp player_return
882+
883+
884+
885+
886+DecompressWithOffset
887+.(
888+ ; Read Offset (0 to 127)
889+ ldx #7
890+ jsr _ReadBits
891+
892+ lda _RegisterBufferHigh ; highpart of buffer adress + register number
893+ sta __auto_write+2 ; Write adress
894+ sta __auto_read+2 ; Read adress
895+
896+ ; Compute wrap around offset...
897+ lda _BufferFrameOffset ; between 0 and 255
898+ clc
899+ adc _DecodedResult ; + Offset Between 00 and 7f
900+ sec
901+ sbc #128 ; -128
902+ tay
903+
904+ ; Read count (7 bits)
905+ ldx #7
906+ jsr _ReadBits
907+
908+ inc _DecodedResult ; 1 to 129
909+
910+
911+ ldx _BufferFrameOffset
912+
913+player_copy_offset_loop
914+
915+__auto_read
916+ lda _PlayerBuffer,y ; Y for reading
917+ iny
918+
919+__auto_write
920+ sta _PlayerBuffer,x ; X for writing
921+
922+ inc _BufferFrameOffset
923+
924+ inx
925+ dec _DecodedResult
926+ bne player_copy_offset_loop
927+
928+ sta _PlayerRegCurrentValue
929+
930+ jmp player_return
931+.)
932+
933+
934+
935+;
936+; Size in bits of each PSG register
937+;
938+_PlayerRegBits
939+ ; Chanel A Frequency
940+ .byt 8
941+ .byt 4
942+
943+ ; Chanel B Frequency
944+ .byt 8
945+ .byt 4
946+
947+ ; Chanel C Frequency
948+ .byt 8
949+ .byt 4
950+
951+ ; Chanel sound generator
952+ .byt 5
953+
954+ ; select
955+ .byt 8
956+
957+ ; Volume A,B,C
958+ .byt 5
959+ .byt 5
960+ .byt 5
961+
962+ ; Wave period
963+ .byt 8
964+ .byt 8
965+
966+ ; Wave form
967+ .byt 8
968+
969+_MusicData
970+#include "build\music.s" ; Generated by ym2mym + bin2txt
971+MusicEnd
972+
973+_TitlePicture
974+#include "build\title_picture.s" ; Generated by pictconv
975+
976+ .bss
977+
978+ .dsb 256-(*&255)
979+
980+ _PlayerBuffer .dsb 256*14 ; $6800 ; .dsb 256*14 (About 3.5 kilobytes)
981+ _PlayerBufferEnd
982+
983+_ScreenAddrLow .dsb 256
984+_ScreenAddrHigh .dsb 256
985+
986+_PictureLoadBufferAddrLow .dsb 256
987+_PictureLoadBufferAddrHigh .dsb 256
988+
989+_EmptySourceScanLine .dsb 256 ; Only zeroes, can be used for special effects
990+_EmptyDestinationScanLine .dsb 256 ; Only zeroes, can be used for special effects
991+
992+
--- users/dbug/UpgradeTime/TheHobbit/osdk_build.bat (nonexistent)
+++ users/dbug/UpgradeTime/TheHobbit/osdk_build.bat (revision 1578)
@@ -0,0 +1,61 @@
1+@ECHO OFF
2+TITLE OSDK
3+
4+::
5+:: Initial check.
6+:: Verify if the SDK is correctly configurated
7+::
8+IF "%OSDK%"=="" GOTO ErCfg
9+
10+set OSDKB=%OSDK%\bin
11+set OSDKNAME=TheHobbit
12+set OSDKDISK=%OSDKNAME%
13+
14+:: Convert the graphical and audio data
15+%OSDKB%\pictconv -u1 -m0 -f6 -o4-TitlePicture data\title.png build\title_picture.s
16+%OSDKB%\pictconv -m0 -f0 -o1 data\font_6x8_oncial.png build\font_6x8.tap
17+
18+%OSDK%\bin\ym2mym -h0 -m15872 data\music.ym build\music.mym
19+%OSDKB%\bin2txt -s1 -f2 build\music.mym build\music.s _Music
20+
21+:: Build the main boot loader (BASIC)
22+%OSDKB%\Bas2Tap -b2t1 -color1 boot.bas build\boot.tap
23+
24+:: Build the intro (assembler)
25+%OSDKB%\Xa -l build\symbols_intro -o build\intro.bin intro.s
26+%OSDKB%\header.exe -h1 -a1 build\intro.bin build\intro.tap $600
27+
28+:: Build the patch (assembler), attach it to the end of the original Hobbit executable
29+%OSDKB%\Xa -l build\symbols_patch -o build\patch.bin patch.s
30+copy /b data\HOBBIT.COM+build\patch.bin build\patched_hobbit.bin
31+
32+:: Merge the debugging symbols of the intro and patch
33+copy /b build\symbols_intro+build\symbols_patch %osdk%\oricutron\symbols
34+
35+:: hobbit.com - 36176 bytes loads/runs at $4fe
36+%OSDKB%\header.exe -h1 -a1 build\patched_hobbit.bin build\hobbit.com $4fe
37+
38+::ECHO ON
39+ECHO Building DSK file
40+pushd build
41+
42+%OSDK%\bin\tap2dsk -iCLS:BOOT boot.tap hobbit.com intro.tap font_6x8.tap %OSDKDISK%.dsk
43+%OSDK%\bin\old2mfm %OSDKDISK%.dsk
44+popd
45+
46+GOTO End
47+
48+
49+::
50+:: Outputs an error message
51+::
52+:ErCfg
53+ECHO == ERROR ==
54+ECHO The Oric SDK was not configured properly
55+ECHO You should have a OSDK environment variable setted to the location of the SDK
56+IF "%OSDKBRIEF%"=="" PAUSE
57+GOTO End
58+
59+
60+:End
61+pause
--- users/dbug/UpgradeTime/TheHobbit/osdk_execute.bat (nonexistent)
+++ users/dbug/UpgradeTime/TheHobbit/osdk_execute.bat (revision 1578)
@@ -0,0 +1,30 @@
1+@ECHO OFF
2+
3+::
4+:: Initial check.
5+:: Verify if the SDK is correctly configurated,
6+::
7+IF "%OSDK%"=="" GOTO ErCfg
8+
9+CALL osdk_build.bat
10+
11+::
12+:: Run the emulator using the common batch
13+::
14+echo %OSDKDISK%
15+ECHO ON
16+CALL %OSDK%\bin\execute.bat
17+GOTO End
18+
19+::
20+:: Outputs an error message about configuration
21+::
22+:ErCfg
23+ECHO == ERROR ==
24+ECHO The Oric SDK was not configured properly
25+ECHO You should have a OSDK environment variable setted to the location of the SDK
26+ECHO ===========
27+IF "%OSDKBRIEF%"=="" PAUSE
28+GOTO End
29+
30+:End
--- users/dbug/UpgradeTime/TheHobbit/patch.s (nonexistent)
+++ users/dbug/UpgradeTime/TheHobbit/patch.s (revision 1578)
@@ -0,0 +1,198 @@
1+;
2+; Improved Hobbit v1.5
3+; NOTE: Ideally I'd like to do more fixes, so please avoid distributing it all over the place.
4+; NOTE2: If this is not finished after one year, feel free to ignore the note above, it just means that "life happened" and this version is better than a non existing better one.
5+;
6+; Version historic:
7+; - 1.0 - 2015-04-13 [Silicebit] First DSK version of the Hobbit (see: https://forum.defence-force.org/viewtopic.php?f=20&t=1225)
8+; Note that attempting to use the SAVE or LOAD commands will still try to use the original tape code.
9+; - 1.1 - 2015-04-14 [Silicebit] Same version, buyt with a INIST so the game autostarts
10+; - 1.2 - 2022-02-23 [Dbug] Added this code that patches the game to speed-up the drawing routines using some multiplication, divide and modulo tables
11+; - 1.3 - 2022-02-24 [Dbug] Replaced the system font by a fancy one ("oncial") to make the game feel a bit more atmospheric
12+; - 1.4 - 2022-02-25 [Dbug] Added an intro picture based on the original game manual artwork
13+; - 1.5 - 2022-02-26 [Dbug] The intro picture now appears with an unroll effect, and a music play in the background
14+;
15+; TODO list:
16+; - Modify the SAVE and LOAD code to use the floppy disk instead of tape
17+; - Add proper credits to the game
18+; - Add a way to show a manual directly on the game
19+;
20+; Information regarding the game:
21+; - HOBBIT.COM is 36176 bytes and loads/runs from $4fe
22+; - There is code at $91B2 which recreates the $400-$4FF area which interfered with the Sedoric code in page 4
23+; - $7422 contains the location of the routine that computes the screen address of a specific pixel
24+; - The $405-$414 area contains a JMP table on various ROM routines patched to different addresses depending if an Oric 1 or Atmos is detected (See: https://forum.defence-force.org/viewtopic.php?p=26656#p26656)
25+; - The saving code is called multiple time for various areas, totally about 3623 bytes (see: https://forum.defence-force.org/viewtopic.php?p=26664#p26664)
26+;
27+
28+ .zero
29+
30+ *= $50
31+
32+tmp0 .dsb 2
33+
34+ .text
35+
36+ *= $924E
37+
38+StartPatch
39+;pause jmp pause ; Uncomment to stop auto-running
40+ sei ; We need to disable the IRQ at least during the ROM to RAM copy
41+
42+copy_rom_to_ram
43+ .(
44+ ; After some extensive digging in The Hobbit code, and some email discussion with Veronika Megler,
45+ ; the conclusion was reached that the game used pretty much all the conventional memory, so the only
46+ ; solution that seemed doable was to use the overlay memory.
47+ ;
48+ ; Since the game also use some of the ROM content (mostly the font, keyboard handling, load and save),
49+ ; we have to make sure that we preserve parts that the game require.
50+ ;
51+ ; The current solution is to copy the entire $C000 to $FFFF area from ROM to RAM, then to selectively
52+ ; patch some areas to store whatever we need.
53+ lda #<$c000
54+ sta tmp0+0
55+ lda #>$c000
56+ sta tmp0+1
57+
58+loop_external
59+ ldy #0
60+loop_page
61+ ldx #%11111111 ; Map $C000-$FFFF to access the BASIC ROM
62+ stx $314
63+ lda (tmp0),y ; Load from ROM
64+
65+ ldx #%11111101 ; Map $C000-$FFFF to access the OVERLAY RAM (ISS suggested that all writes modify overlay, selected or not)
66+ stx $314
67+ sta (tmp0),y ; Save to RAM
68+
69+ iny
70+ bne loop_page
71+
72+ inc tmp0+1
73+ bne loop_external
74+ .)
75+
76+
77+generate_tables
78+ .(
79+ ; Generate the scanline table
80+ lda #<$a000+2 ; $00
81+ sta tmp0+0
82+ lda #>$a000+2 ; $A0
83+ sta tmp0+1
84+
85+ ldx #127
86+loop_screen_address
87+ clc ; generate two bytes screen adress
88+ lda tmp0+0
89+ sta _HiresAddrLow,x
90+ adc #40
91+ sta tmp0+0
92+ lda tmp0+1
93+ sta _HiresAddrHigh,x
94+ adc #0
95+ sta tmp0+1
96+
97+ dex
98+ bpl loop_screen_address
99+
100+ ; Generate the mod6/div6 table
101+ lda #0 ; cur div
102+ tay ; cur mod
103+ tax
104+loop_div_mod
105+ sta _Div6,x ; $C855
106+ pha
107+ tya
108+ sta _Mod6,x ; $C955
109+ pla
110+ iny
111+ cpy #6
112+ bne skip_mod
113+ ldy #0
114+ adc #0 ; carry = 1!
115+skip_mod
116+
117+ inx
118+ bne loop_div_mod
119+ .)
120+
121+
122+patch_hobbit
123+ .(
124+ ; Replace the game routine that compute the screen memory address of a specific pixel by oa more efficient one.
125+ ; Note that this new routine requires the _Div6, _Mod6, _HiresAddrLow and _HiresAddrHigh to be patched in the overlay copy of the BASIC ROM
126+ ldx #SizeComputeScreenAddress
127+loop_patch
128+ lda ComputeScreenAddress-1,x
129+ sta $7A22-1,x
130+ dex
131+ bne loop_patch
132+ .)
133+
134+copy_ram_font_to_rom
135+ .(
136+ ; ROM Font is stored from $FC78 to $FF77 = 768 bytes = 3*256
137+ ; We recopy whatever is in the original RAM version of from (from $B400 to $B7FF) to the ROM area.
138+ ; The first 32 characters are skipped because they are not actually displayable.
139+ ldx #0
140+loop_patch
141+ lda $B400+8*32+256*0,x
142+ sta $fc78+256*0-8,x
143+ lda $B400+8*32+256*1,x
144+ sta $fc78+256*1-8,x
145+ lda $B400+8*32+256*2,x
146+ sta $fc78+256*2-8,x
147+ dex
148+ bne loop_patch
149+ .)
150+
151+
152+start_game
153+ cli ; Enable the IRQ again
154+ jmp $91B2 ; What the original did in 04FE
155+
156+ComputeScreenAddress
157+ .(
158+ * = $7A22 ; This routine is assembled at a different address than the rest of the program
159+ begin
160+ ; Mul 40
161+ ldx $31
162+ lda _HiresAddrLow,x
163+ sta $38
164+ lda _HiresAddrHigh,x
165+ sta $39
166+
167+ ; Div 6
168+ ldx $30
169+ lda _Div6-14,x
170+ tay
171+ lda _Mod6-14,x
172+
173+ tax
174+ lda ($38),y
175+ rts
176++SizeComputeScreenAddress=*-begin
177+ *=ComputeScreenAddress+SizeComputeScreenAddress ; Restore the normal program counter
178+.)
179+
180+
181+; And some final information string, so we can easily find which version people are swapping around
182+ .byt "Improved Hobbit v1.5 - Please report any issue to dbug@defence-force.org"
183+
184+; Just so log code to check how large this patch data has become
185+EndPatch
186+#echo Patch size:
187+#print (EndPatch - StartPatch)
188+
189+ .bss
190+
191+ *= $C855 ; Erase the FOR command
192+_Div6 .dsb 256 ; Values divided by 6
193+_Mod6 .dsb 256 ; Values modulo 6
194+
195+ *= $F37F ; Erase the CIRCLE command
196+_HiresAddrLow .dsb 128 ; Values multiplied by 40 + a000
197+_HiresAddrHigh .dsb 128 ; Values multiplied by 40 + a000
198+
Show on old repository browser